Skip to content

Instantly share code, notes, and snippets.

@bruceharris
Created July 30, 2012 19:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bruceharris/3209548 to your computer and use it in GitHub Desktop.
Save bruceharris/3209548 to your computer and use it in GitHub Desktop.
JavaScript I - Variables, Functions, and Scope

JavaScript II - Objects, Arrays and Booleans

Content and target audience

JavaScript II - Objects, Arrays, and Booleans

Laying the foundation for object oriented programing in JavaScript.

Constructor functions, prototypes, the this keyword, object inheritance and other related topics will be covered in later talks.

Emphasis on behavior/syntax specific to JavaScript (as compared to other languages).

You are familiar with basics of functional programming in JavaScript (covered in JavaScript I - Variables, Functions, and Scope)

Resources and tools

Not as I do…​

Avoid document.writeln() - not useful in real life, but useful for examples

Object literals

var customer = {
    account: 1003,
    name: "Rick Danko"
};

Accessing properties

Both bracket notatation and dot notation can be used to access properties

document.writeln(customer.account);
document.writeln(customer['account']);
document.writeln(customer.account == customer['account']);

var p = "name";
document.writeln(customer[p]);  // can we do this?
p = "account";
document.writeln(customer[p]);  // can we do this?

Adding properties to an object

Both bracket notatation and dot notation can be used to assign/add properties

var customer = {};
customer.account = 1003;
customer['name'] = "Rick Danko";

Deleting properties

The delete keyword

var customer = {
    account: 1003,
    name: "Rick Danko"
};
delete customer.account;
document.writeln(customer.account); // ?

Accessing properties of an object literal

Parentheses required

function numberToText(num){
    return ({
        1: 'one',
        2: 'two'
        // ...
    })[num];
}
document.writeln(numberToText(1));
document.writeln(numberToText(3)); // ?

Property names

var o = {
    "var": 1,             // Can we use JavaScript keywords?
    "+": 2,               // Symbols?
    "fat black cat": 4    // Spaces?
};

Yes, with 2 caveats

  • Wrap property names in quotes in object literals

  • Use bracket notation, not dot notation, to access or assign properties

Methods

var o = {
    f: function () {
        // can an object property contain a function?
    }
};

Yes, functions are first class citizens in JavaScript. This is how "methods" are implemented in JavaScript.

Object type

var o = {a: 1};
document.writeln(typeof o);

Some are more equal than others

document.writeln(0 == '0');
document.writeln(0 === '0');
document.writeln(0 != '0');
document.writeln(0 !== '0');

"Truthy" and "Falsy"

function write(s){
    document.writeln(s + '<br>');
}
write(1 ? 'yes' : 'no');
write(0 ? 'yes' : 'no');
write('hi' ? 'yes' : 'no');
write('' ? 'yes' : 'no');
write('0' ? 'yes' : 'no');
write(null ? 'yes' : 'no');
write(undefined ? 'yes' : 'no');
write( ({}).foo ? 'yes' : 'no');

Short circuit evaluation

var o = {
    bar: "hello",
    baz: 0
};
document.writeln(o.foo || "o does not have a foo property");
document.writeln(o.bar && "o.bar has a truthy value");
document.writeln(o.baz || "o.baz has a falsy value");

in operator

(string in object) is a boolean expression

var o = { a: 1 };

document.writeln('a' in o);  // does o have a property named a?
document.writeln('b' in o);  // does o have a property named b?

in operator

var o = { a: false };

document.writeln('a' in o);  // true or false?

for ... in loop

Enumerates over enumerable properties of an object

var o = {
    a: 1,
    b: 2,
    c: 3
};
for (var prop in o) {
    document.writeln("| " + prop + ':' + o[prop] + " |");
}

The global object

  • Every JavaScript environment has a single global object

  • All global variables are properties of this object

  • In web browsers, the global object is window

var g1 = "Just an innocent global";
document.writeln(window.g1 == g1);

window.g2 = "Another global";
document.writeln(g2);

Accessing a "shadowed" global

var g = 1;
function f(){
    var g = 2;
    // can we access the global g here?
}
f();

Accessing a "shadowed" global

var g = 1;
function f(){
    var g = 2;
    document.writeln(window.g);
}
f();

Accessing "shadowed" non-globals?

var g = 1;
function f(){
    var g = 2;
    (function(){
        var g = 3;
        // can we access the "middle" g here?
    })();
}
f();

Sorry, no

Array literals

var a = [21, 32, 25];
document.writeln(a[0]);
document.writeln(a[1]);
document.writeln(a[2]);
document.writeln(a[3]);
document.writeln(a.length);

Mixed type arrays

var a = [14, "shoe", {a: 8}];
a.push(3.1415);

document.writeln(a[3]);
document.writeln(a[2].a);

Some useful array methods

var a = ["coffee", "tea", "beer"];
document.writeln(a.join());
document.writeln(a.join(" or ") + "?");
document.writeln(a.pop() + " please");
document.writeln(a.join());

Nested object / array structures

var a = [14, "shoe", {a: 8}];
a.push(3.1415);
a.push({b: [9, 4, ["a", "r"]]});

document.writeln(a[3]);
document.writeln(a[2].a);
document.writeln(a[4]['b'][2][1]);

JavaScript does not have real arrays

var a = [21, 32, 25];
document.writeln(typeof a);

a[9] = "huh?";
document.writeln(a.length);

delete a[1];
document.writeln(a[1]); // did array shift to fill in gap left at index 1?

var s = "2";
document.writeln(a[s]); // can we access array elements with a string index?

Functional programming with arrays

function forEach(arr, fn) {
    for (var i = 0; i < arr.length; i++) fn(arr[i]);
}
function printPlus1(x){
    document.writeln((x + 1) + '<br>');
}
var a = [21, 32, 25];
forEach(a, printPlus1);

Objects as namespaces

var MyApp = {
    Module1: {
        // public functions (methods) and variables (properties)
    },
    Module2: (function(){  // note enclosing parentheses - immediate function
        // private code and variables
        return {
            // public properties/methods
        };
    })(),
    Module3: function(){
        // just a function
    }
};

Function returning an object

function makeCustomer(account, name){
    return {
        account: account,
        name: name
    };
}

Objects with methods and private variables

function makeCounter(){
    var count = 0;
    function reset(newCount){
        count = newCount || 0;
    }
    function current(){
        return count;
    }
    return {
        reset: reset,
        current: current,
        increment: function (amount) {
            if (typeof amount === 'undefined') amount = 1;
            count += amount;
        }
    };
}

Exercise 1

function map(arr, fn){
    // your code here
}
function plus1(x){
    return x + 1;
}
var a1 = [21, 32, 25];
var a2 = map(a1, plus1); // [22, 33, 26]

Exercise 2

function translateNote(note){
    switch (note) {
        case 'c':
            return 'dough';
            break;
        case 'd':
            return 'ray';
            break;
        default:
            return 'I only know 2 notes';
    }
}
document.writeln(translateNote('c')); // 'dough'
document.writeln(translateNote('d')); // 'ray'
document.writeln(translateNote('e')); // 'I only know 2 notes'

// rewrite translateNote to use only 1 return statement
// hint: don't use switch

Exercise 3

function makeCustomer(name, account){
    /****
      your code here

      customer object has...
       - a name property containing the customer's name
       - an account property containing the customer's account number
       - an addOrder method that takes 1 argument: order number
       - a getOrders method that returns a string containing info about
         customer's orders, per below example
       - info about orders can only be accessed via the getOrders method
     */
}

var bob = makeCustomer('Bob', 5673);
document.writeln(bob.getOrders()); // "Bob has no orders"
bob.addOrder(90023);
document.writeln(bob.getOrders()); // "Bob's order: 90023"
bob.addOrder(90028);
document.writeln(bob.getOrders()); // "Bob's orders: 90023, 90028"

Exercise 4

function reduce(arr, fn){
    // your code here
}
function add(x, y){
    return x + y;
}
function mult(x, y){
    return x * y;
}
document.writeln(reduce([3, 7, 2], add));   // 12
document.writeln(reduce([3, 7, 2], mult));   // 42
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>JavaScript II - Objects, Arrays and Booleans</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="copyright" content="Copyright &#169; Bruce Harris, 8/2/12" />
<meta name="generator" content="AsciiDoc 8.6.7" />
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
pre {
padding: 0;
margin: 0;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
tt {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
.monospaced {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/* slidy.css
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
/*
SJR: 2010-09-29: Modified for AsciiDoc slidy backend.
Mostly just commented out stuff that is handled by AsciiDoc's CSS files.
*/
body
{
margin: 0 0 0 0;
padding: 0 0 0 0;
width: 100%;
height: 100%;
color: black;
background-color: white;
/*
font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
*/
font-size: 14pt;
}
div.toolbar {
position: fixed; z-index: 200;
top: auto; bottom: 0; left: 0; right: 0;
height: 1.2em; text-align: right;
padding-left: 1em;
padding-right: 1em;
font-size: 60%;
color: red;
background-color: rgb(240,240,240);
border-top: solid 1px rgb(180,180,180);
}
div.toolbar span.copyright {
color: black;
margin-left: 0.5em;
}
div.initial_prompt {
position: absolute;
z-index: 1000;
bottom: 1.2em;
width: 90%;
background-color: rgb(200,200,200);
opacity: 0.35;
background-color: rgb(200,200,200, 0.35);
cursor: pointer;
}
div.initial_prompt p.help {
text-align: center;
}
div.initial_prompt p.close {
text-align: right;
font-style: italic;
}
div.slidy_toc {
position: absolute;
z-index: 300;
width: 60%;
max-width: 30em;
height: 30em;
overflow: auto;
top: auto;
right: auto;
left: 4em;
bottom: 4em;
padding: 1em;
background: rgb(240,240,240);
border-style: solid;
border-width: 2px;
font-size: 60%;
}
div.slidy_toc .toc_heading {
text-align: center;
width: 100%;
margin: 0;
margin-bottom: 1em;
border-bottom-style: solid;
border-bottom-color: rgb(180,180,180);
border-bottom-width: 1px;
}
div.slide {
z-index: 20;
margin: 0 0 0 0;
padding-top: 0;
padding-bottom: 0;
padding-left: 20px;
padding-right: 20px;
border-width: 0;
clear: both;
top: 0;
bottom: 0;
left: 0;
right: 0;
line-height: 120%;
background-color: transparent;
}
div.background {
display: none;
}
div.handout {
margin-left: 20px;
margin-right: 20px;
}
div.slide.titlepage {
text-align: center;
}
div.slide.titlepage.h1 {
padding-top: 10%;
}
div.slide h1 {
padding-left: 0;
padding-right: 20pt;
padding-top: 4pt;
padding-bottom: 4pt;
margin-top: 0;
margin-left: 0;
margin-right: 60pt;
margin-bottom: 0.5em;
display: block;
font-size: 160%;
line-height: 1.2em;
background: transparent;
}
div.toc {
position: absolute;
top: auto;
bottom: 4em;
left: 4em;
right: auto;
width: 60%;
max-width: 30em;
height: 30em;
border: solid thin black;
padding: 1em;
background: rgb(240,240,240);
color: black;
z-index: 300;
overflow: auto;
display: block;
visibility: visible;
}
div.toc-heading {
width: 100%;
border-bottom: solid 1px rgb(180,180,180);
margin-bottom: 1em;
text-align: center;
}
/*
pre {
font-size: 80%;
font-weight: bold;
line-height: 120%;
padding-top: 0.2em;
padding-bottom: 0.2em;
padding-left: 1em;
padding-right: 1em;
border-style: solid;
border-left-width: 1em;
border-top-width: thin;
border-right-width: thin;
border-bottom-width: thin;
border-color: #95ABD0;
color: #00428C;
background-color: #E4E5E7;
}
*/
/*
li pre { margin-left: 0; }
blockquote { font-style: italic }
img { background-color: transparent }
p.copyright { font-size: smaller }
*/
.center { text-align: center }
.footnote { font-size: smaller; margin-left: 2em; }
/*
a img { border-width: 0; border-style: none }
*/
a:visited { color: navy }
a:link { color: navy }
a:hover { color: red; text-decoration: underline }
a:active { color: red; text-decoration: underline }
a {text-decoration: none}
.navbar a:link {color: white}
.navbar a:visited {color: yellow}
.navbar a:active {color: red}
.navbar a:hover {color: red}
/*
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
li { margin-left: 0.5em; margin-top: 0.5em; }
li li { font-size: 85%; font-style: italic }
li li li { font-size: 85%; font-style: normal }
*/
div dt
{
margin-left: 0;
margin-top: 1em;
margin-bottom: 0.5em;
font-weight: bold;
}
div dd
{
margin-left: 2em;
margin-bottom: 0.5em;
}
/*
p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
margin-left: 1em;
margin-right: 1em;
}
*/
p.subhead { font-weight: bold; margin-top: 2em; }
.smaller { font-size: smaller }
.bigger { font-size: 130% }
/*
td,th { padding: 0.2em }
*/
ul {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ol {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
/*
ul li {
list-style: square;
margin: 0.1em 0em 0.6em 0;
padding: 0 0 0 0;
line-height: 140%;
}
ol li {
margin: 0.1em 0em 0.6em 1.5em;
padding: 0 0 0 0px;
line-height: 140%;
list-style-type: decimal;
}
li ul li {
font-size: 85%;
font-style: italic;
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li li ul li {
font-size: 85%;
font-style: normal;
list-style-type: circle;
background: transparent;
padding: 0 0 0 0;
}
li li li ul li {
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li ol li {
list-style-type: decimal;
}
li li ol li {
list-style-type: decimal;
}
*/
/*
setting class="outline" on ol or ul makes it behave as an
ouline list where blocklevel content in li elements is
hidden by default and can be expanded or collapsed with
mouse click. Set class="expand" on li to override default
*/
ol.outline li:hover { cursor: pointer }
ol.outline li.nofold:hover { cursor: default }
ul.outline li:hover { cursor: pointer }
ul.outline li.nofold:hover { cursor: default }
ol.outline { list-style:decimal; }
ol.outline ol { list-style-type:lower-alpha }
ol.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
ul.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
/* for slides with class "title" in table of contents */
a.titleslide { font-weight: bold; font-style: italic }
/*
hide images for work around for save as bug
where browsers fail to save images used by CSS
*/
img.hidden { display: none; visibility: hidden }
div.initial_prompt { display: none; visibility: hidden }
div.slide {
visibility: visible;
position: inherit;
}
div.handout {
border-top-style: solid;
border-top-width: thin;
border-top-color: black;
}
@media screen {
.hidden { display: none; visibility: visible }
div.slide.hidden { display: block; visibility: visible }
div.handout.hidden { display: block; visibility: visible }
div.background { display: none; visibility: hidden }
body.single_slide div.initial_prompt { display: block; visibility: visible }
body.single_slide div.background { display: block; visibility: visible }
body.single_slide div.background.hidden { display: none; visibility: hidden }
body.single_slide .invisible { visibility: hidden }
body.single_slide .hidden { display: none; visibility: hidden }
body.single_slide div.slide { position: absolute }
body.single_slide div.handout { display: none; visibility: hidden }
}
@media print {
.hidden { display: block; visibility: visible }
/*
div.slide pre { font-size: 60%; padding-left: 0.5em; }
*/
div.toolbar { display: none; visibility: hidden; }
div.slidy_toc { display: none; visibility: hidden; }
div.background { display: none; visibility: hidden; }
div.slide { page-break-before: always }
/* :first-child isn't reliable for print media */
div.slide.first-slide { page-break-before: avoid }
}
/* SJR: AsciiDoc slidy backend tweaks */
ol, ul {
margin: 0.8em 1.5em 0.8em 1.8em;
}
li > ul, li > ol {
margin-top: 0.5em;
}
.outline > li.folded,
.outline > li.unfolded {
color: #527bbd;
}
ul > li{ color: #aaa; }
ul > li > *, ol > li > * { color: black; }
li {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
/*
pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
<script type="text/javascript">
/*<![CDATA[*/
/* slidy.js
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
// the slidy object implementation
var w3c_slidy = {
// classify which kind of browser we're running under
ns_pos: (typeof window.pageYOffset!='undefined'),
khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false),
opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false),
ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false),
iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false),
ie: (typeof document.all != "undefined" && !this.opera),
ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1),
ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1),
ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1),
ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1),
keyboardless: (this.ipad || this.iphone),
// are we running as XHTML? (doesn't work on Opera)
is_xhtml: /xml/.test(document.contentType),
slide_number: 0, // integer slide count: 0, 1, 2, ...
slide_number_element: null, // element containing slide number
slides: [], // set to array of slide div's
notes: [], // set to array of handout div's
backgrounds: [], // set to array of background div's
toolbar: null, // element containing toolbar
title: null, // document title
last_shown: null, // last incrementally shown item
eos: null, // span element for end of slide indicator
toc: null, // table of contents
outline: null, // outline element with the focus
selected_text_len: 0, // length of drag selection on document
view_all: 0, // 1 to view all slides + handouts
want_toolbar: true, // user preference to show/hide toolbar
mouse_click_enabled: true, // enables left click for next slide
scroll_hack: 0, // IE work around for position: fixed
disable_slide_click: false, // used by clicked anchors
lang: "en", // updated to language specified by html file
help_anchor: null, // used for keyboard focus hack in showToolbar()
help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html",
help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " +
"or Pg Up and Pg Dn. Use S and B to change font size.",
size_index: 0,
size_adjustment: 0,
sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
"22pt", "24pt", "26pt", "28pt", "30pt", "32pt"),
// needed for efficient resizing
last_width: 0,
last_height: 0,
// Needed for cross browser support for relative width/height on
// object elements. The work around is to save width/height attributes
// and then to recompute absolute width/height dimensions on resizing
objects: [],
// attach initialiation event handlers
set_up: function () {
var init = function() { w3c_slidy.init(); };
if (typeof window.addEventListener != "undefined")
window.addEventListener("load", init, false);
else
window.attachEvent("onload", init);
},
hide_slides: function () {
if (document.body && !w3c_slidy.initialized)
document.body.style.visibility = "hidden";
else
setTimeout(w3c_slidy.hide_slides, 50);
},
// hack to persuade IE to compute correct document height
// as needed for simulating fixed positioning of toolbar
ie_hack: function () {
window.resizeBy(0,-1);
window.resizeBy(0, 1);
},
init: function () {
//alert("slidy starting test 10");
document.body.style.visibility = "visible";
w3c_slidy_i18n.init();
this.add_toolbar();
this.wrap_implicit_slides();
this.collect_slides();
this.collect_notes();
this.collect_backgrounds();
this.objects = document.body.getElementsByTagName("object");
this.patch_anchors();
this.slide_number = this.find_slide_number(location.href);
window.offscreenbuffering = true;
this.size_adjustment = this.find_size_adjust();
this.time_left = this.find_duration();
this.hide_image_toolbar(); // suppress IE image toolbar popup
this.init_outliner(); // activate fold/unfold support
this.title = document.title;
// work around for opera bug
this.is_xhtml = (document.body.tagName == "BODY" ? false : true);
if (this.slides.length > 0)
{
var slide = this.slides[this.slide_number];
if (this.slide_number > 0)
{
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
this.set_eos_status(true);
}
else
{
this.last_shown = null;
this.set_visibility_all_incremental("hidden");
this.set_eos_status(!this.next_incremental_item(this.last_shown));
}
this.set_location();
this.add_class(this.slides[0], "first-slide");
w3c_slidy.show_slide(slide);
}
this.toc = this.table_of_contents();
this.add_initial_prompt();
// bind event handlers without interfering with custom page scripts
// Tap events behave too weirdly to support clicks reliably on
// iPhone and iPad, so exclude these from click handler
if (!this.keyboardless)
this.add_listener(document.body, "click", this.mouse_button_click);
this.add_listener(document, "keydown", this.key_down);
this.add_listener(document, "keypress", this.key_press);
this.add_listener(window, "resize", this.resized);
this.add_listener(window, "scroll", this.scrolled);
this.add_listener(window, "unload", this.unloaded);
if (!document.body.onclick)
document.body.onclick = function () { };
this.single_slide_view();
//this.set_location();
this.resized();
if (this.ie7)
setTimeout(w3c_slidy.ie_hack, 100);
this.show_toolbar();
// for back button detection
setInterval(function () { w3c_slidy.check_location(); }, 200);
w3c_slidy.initialized = true;
},
// create div element with links to each slide
table_of_contents: function () {
var toc = this.create_element("div");
this.add_class(toc, "slidy_toc hidden");
//toc.setAttribute("tabindex", "0");
var heading = this.create_element("div");
this.add_class(heading, "toc-heading");
heading.innerHTML = "Table of Contents".localize();
toc.appendChild(heading);
var previous = null;
for (var i = 0; i < this.slides.length; ++i)
{
var title = this.has_class(this.slides[i], "title");
var num = document.createTextNode((i + 1) + ". ");
toc.appendChild(num);
var a = this.create_element("a");
a.setAttribute("href", "#(" + (i+1) + ")");
if (title)
this.add_class(a, "titleslide");
var name = document.createTextNode(this.slide_name(i));
a.appendChild(name);
a.onclick = w3c_slidy.toc_click;
a.onkeydown = w3c_slidy.toc_keydown;
a.previous = previous;
if (previous)
previous.next = a;
toc.appendChild(a);
if (i == 0)
toc.first = a;
if (i < this.slides.length - 1)
{
var br = this.create_element("br");
toc.appendChild(br);
}
previous = a;
}
toc.focus = function () {
if (this.first)
this.first.focus();
}
toc.onmouseup = w3c_slidy.mouse_button_up;
toc.onclick = function (e) {
e||(e=window.event);
if (w3c_slidy.selected_text_len <= 0)
w3c_slidy.hide_table_of_contents();
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
};
document.body.insertBefore(toc, document.body.firstChild);
return toc;
},
is_shown_toc: function () {
return !w3c_slidy.has_class(w3c_slidy.toc, "hidden");
},
show_table_of_contents: function () {
w3c_slidy.remove_class(w3c_slidy.toc, "hidden");
var toc = w3c_slidy.toc;
toc.focus();
if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0)
setTimeout(w3c_slidy.ie_hack, 100);
},
hide_table_of_contents: function () {
w3c_slidy.add_class(w3c_slidy.toc, "hidden");
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
},
toggle_table_of_contents: function () {
if (w3c_slidy.is_shown_toc())
w3c_slidy.hide_table_of_contents();
else
w3c_slidy.show_table_of_contents();
},
// called on clicking toc entry
toc_click: function (e) {
if (!e)
e = window.event;
var target = w3c_slidy.get_target(e);
if (target && target.nodeType == 1)
{
var uri = target.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
}
w3c_slidy.hide_table_of_contents(e);
if (w3c_slidy.ie7) w3c_slidy.ie_hack();
w3c_slidy.stop_propagation(e);
return w3c_slidy.cancel(e);
},
// called onkeydown for toc entry
toc_keydown: function (event) {
var key;
if (!event)
var event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey)
return true;
if (key == 13)
{
var uri = this.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
w3c_slidy.hide_table_of_contents();
if (self.ie7)
w3c_slidy.ie_hack();
return w3c_slidy.cancel(event);
}
if (key == 40 && this.next)
{
this.next.focus();
return w3c_slidy.cancel(event);
}
if (key == 38 && this.previous)
{
this.previous.focus();
return w3c_slidy.cancel(event);
}
return true;
},
// ### OBSOLETE ###
before_print: function () {
this.show_all_slides();
this.hide_toolbar();
alert("before print");
},
// ### OBSOLETE ###
after_print: function () {
if (!this.view_all)
{
this.single_slide_view();
this.show_toolbar();
}
alert("after print");
},
// ### OBSOLETE ###
print_slides: function () {
this.before_print();
window.print();
this.after_print();
},
// ### OBSOLETE ?? ###
toggle_view: function () {
if (this.view_all)
{
this.single_slide_view();
this.show_toolbar();
this.view_all = 0;
}
else
{
this.show_all_slides();
this.hide_toolbar();
this.view_all = 1;
}
},
// prepare for printing ### OBSOLETE ###
show_all_slides: function () {
this.remove_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
},
// restore after printing ### OBSOLETE ###
single_slide_view: function () {
this.add_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
},
// suppress IE's image toolbar pop up
hide_image_toolbar: function () {
if (!this.ns_pos)
{
var images = document.getElementsByTagName("IMG");
for (var i = 0; i < images.length; ++i)
images[i].setAttribute("galleryimg", "no");
}
},
unloaded: function (e) {
//alert("unloaded");
},
// Safari and Konqueror don't yet support getComputedStyle()
// and they always reload page when location.href is updated
is_KHTML: function () {
var agent = navigator.userAgent;
return (agent.indexOf("KHTML") >= 0 ? true : false);
},
// find slide name from first h1 element
// default to document title + slide number
slide_name: function (index) {
var name = null;
var slide = this.slides[index];
var heading = this.find_heading(slide);
if (heading)
name = this.extract_text(heading);
if (!name)
name = this.title + "(" + (index + 1) + ")";
name.replace(/\&/g, "&amp;");
name.replace(/\</g, "&lt;");
name.replace(/\>/g, "&gt;");
return name;
},
// find first h1 element in DOM tree
find_heading: function (node) {
if (!node || node.nodeType != 1)
return null;
if (node.nodeName == "H1" || node.nodeName == "h1")
return node;
var child = node.firstChild;
while (child)
{
node = this.find_heading(child);
if (node)
return node;
child = child.nextSibling;
}
return null;
},
// recursively extract text from DOM tree
extract_text: function (node) {
if (!node)
return "";
// text nodes
if (node.nodeType == 3)
return node.nodeValue;
// elements
if (node.nodeType == 1)
{
node = node.firstChild;
var text = "";
while (node)
{
text = text + this.extract_text(node);
node = node.nextSibling;
}
return text;
}
return "";
},
// find copyright text from meta element
find_copyright: function () {
var name, content;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "copyright")
return content;
}
return null;
},
find_size_adjust: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "font-size-adjustment")
return 1 * content;
}
return 1;
},
// <meta name="duration" content="20" /> for 20 minutes
find_duration: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "duration")
return 60000 * content;
}
return null;
},
replace_by_non_breaking_space: function (str) {
for (var i = 0; i < str.length; ++i)
str[i] = 160;
},
// ### CHECK ME ### is use of "li" okay for text/html?
// for XHTML do we also need to specify namespace?
init_outliner: function () {
var items = document.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i)
{
var target = items[i];
if (!this.has_class(target.parentNode, "outline"))
continue;
target.onclick = this.outline_click;
/* ### more work needed for IE6
if (!this.ns_pos)
{
target.onmouseover = this.hover_outline;
target.onmouseout = this.unhover_outline;
}
*/
if (this.foldable(target))
{
target.foldable = true;
target.onfocus = function () {w3c_slidy.outline = this;};
target.onblur = function () {w3c_slidy.outline = null;};
if (!target.getAttribute("tabindex"))
target.setAttribute("tabindex", "0");
if (this.has_class(target, "expand"))
this.unfold(target);
else
this.fold(target);
}
else
{
this.add_class(target, "nofold");
target.visible = true;
target.foldable = false;
}
}
},
foldable: function (item) {
if (!item || item.nodeType != 1)
return false;
var node = item.firstChild;
while (node)
{
if (node.nodeType == 1 && this.is_block(node))
return true;
node = node.nextSibling;
}
return false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
fold: function (item) {
if (item)
{
this.remove_class(item, "unfolded");
this.add_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.add_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
unfold: function (item) {
if (item)
{
this.add_class(item, "unfolded");
this.remove_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.remove_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = true;
},
outline_click: function (e) {
if (!e)
e = window.event;
var rightclick = false;
var target = w3c_slidy.get_target(e);
while (target && target.visible == undefined)
target = target.parentNode;
if (!target)
return true;
if (e.which)
rightclick = (e.which == 3);
else if (e.button)
rightclick = (e.button == 2);
if (!rightclick && target.visible != undefined)
{
if (target.foldable)
{
if (target.visible)
w3c_slidy.fold(target);
else
w3c_slidy.unfold(target);
}
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
}
return false;
},
add_initial_prompt: function () {
var prompt = this.create_element("div");
prompt.setAttribute("class", "initial_prompt");
var p1 = this.create_element("p");
prompt.appendChild(p1);
p1.setAttribute("class", "help");
if (this.keyboardless)
p1.innerHTML = "Tap footer to move to next slide";
else
p1.innerHTML = "Space or Right Arrow to move to next " +
"slide, click help below for more details";
this.add_listener(prompt, "click", function (e) {
document.body.removeChild(prompt);
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
});
document.body.appendChild(prompt);
this.initial_prompt = prompt;
setTimeout(function() {document.body.removeChild(prompt);}, 5000);
},
add_toolbar: function () {
var counter, page;
this.toolbar = this.create_element("div");
this.toolbar.setAttribute("class", "toolbar");
// a reasonably behaved browser
if (this.ns_pos || !this.ie6)
{
var right = this.create_element("div");
right.setAttribute("style", "float: right; text-align: right");
counter = this.create_element("span")
counter.innerHTML = "slide".localize() + " n/m";
right.appendChild(counter);
this.toolbar.appendChild(right);
var left = this.create_element("div");
left.setAttribute("style", "text-align: left");
// global end of slide indicator
this.eos = this.create_element("span");
this.eos.innerHTML = "* ";
left.appendChild(this.eos);
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
left.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
left.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
left.appendChild(contents);
var gap2 = document.createTextNode(" ");
left.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.className = "copyright";
span.innerHTML = copyright;
left.appendChild(span);
}
this.toolbar.setAttribute("tabindex", "0");
this.toolbar.appendChild(left);
}
else // IE6 so need to work around its poor CSS support
{
this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute");
this.toolbar.style.zIndex = "200";
this.toolbar.style.width = "99.9%";
this.toolbar.style.height = "1.2em";
this.toolbar.style.top = "auto";
this.toolbar.style.bottom = "0";
this.toolbar.style.left = "0";
this.toolbar.style.right = "0";
this.toolbar.style.textAlign = "left";
this.toolbar.style.fontSize = "60%";
this.toolbar.style.color = "red";
this.toolbar.borderWidth = 0;
this.toolbar.className = "toolbar";
this.toolbar.style.background = "rgb(240,240,240)";
// would like to have help text left aligned
// and page counter right aligned, floating
// div's don't work, so instead use nested
// absolutely positioned div's.
var sp = this.create_element("span");
sp.innerHTML = "&nbsp;&nbsp;*&nbsp;";
this.toolbar.appendChild(sp);
this.eos = sp; // end of slide indicator
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
this.toolbar.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
this.toolbar.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:toggleTableOfContents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
this.toolbar.appendChild(contents);
var gap2 = document.createTextNode(" ");
this.toolbar.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.innerHTML = copyright;
span.style.color = "black";
span.style.marginLeft = "0.5em";
this.toolbar.appendChild(span);
}
counter = this.create_element("div")
counter.style.position = "absolute";
counter.style.width = "auto"; //"20%";
counter.style.height = "1.2em";
counter.style.top = "auto";
counter.style.bottom = 0;
counter.style.right = "0";
counter.style.textAlign = "right";
counter.style.color = "red";
counter.style.background = "rgb(240,240,240)";
counter.innerHTML = "slide".localize() + " n/m";
this.toolbar.appendChild(counter);
}
// ensure that click isn't passed through to the page
this.toolbar.onclick =
function (e) {
if (!e)
e = window.event;
var target = e.target;
if (!target && e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target && target.nodeType == 3)
target = target.parentNode;
w3c_slidy.stop_propagation(e);
if (target && target.nodeName.toLowerCase() != "a")
w3c_slidy.mouse_button_click(e);
};
this.slide_number_element = counter;
this.set_eos_status(false);
document.body.appendChild(this.toolbar);
},
// wysiwyg editors make it hard to use div elements
// e.g. amaya loses the div when you copy and paste
// this function wraps div elements around implicit
// slides which start with an h1 element and continue
// up to the next heading or div element
wrap_implicit_slides: function () {
var i, heading, node, next, div;
var headings = document.getElementsByTagName("h1");
if (!headings)
return;
for (i = 0; i < headings.length; ++i)
{
heading = headings[i];
if (heading.parentNode != document.body)
continue;
node = heading.nextSibling;
div = document.createElement("div");
this.add_class(div, "slide");
document.body.replaceChild(div, heading);
div.appendChild(heading);
while (node)
{
if (node.nodeType == 1 && // an element
(node.nodeName == "H1" ||
node.nodeName == "h1" ||
node.nodeName == "DIV" ||
node.nodeName == "div"))
break;
next = node.nextSibling;
node = document.body.removeChild(node);
div.appendChild(node);
node = next;
}
}
},
// return new array of all slides
collect_slides: function () {
var slides = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "slide"))
{
// add slide to collection
slides[slides.length] = div;
// hide each slide as it is found
this.add_class(div, "hidden");
// add dummy <br/> at end for scrolling hack
var node1 = document.createElement("br");
div.appendChild(node1);
var node2 = document.createElement("br");
div.appendChild(node2);
}
else if (this.has_class(div, "background"))
{ // work around for Firefox SVG reload bug
// which otherwise replaces 1st SVG graphic with 2nd
div.style.display = "block";
}
}
this.slides = slides;
},
// return new array of all <div class="handout">
collect_notes: function () {
var notes = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "handout"))
{
// add note to collection
notes[notes.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.notes = notes;
},
// return new array of all <div class="background">
// including named backgrounds e.g. class="background titlepage"
collect_backgrounds: function () {
var backgrounds = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "background"))
{
// add background to collection
backgrounds[backgrounds.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.backgrounds = backgrounds;
},
// set click handlers on all anchors
patch_anchors: function () {
var self = w3c_slidy;
var handler = function (event) {
// compare this.href with location.href
// for link to another slide in this doc
if (self.page_address(this.href) == self.page_address(location.href))
{
// yes, so find new slide number
var newslidenum = self.find_slide_number(this.href);
if (newslidenum != self.slide_number)
{
var slide = self.slides[self.slide_number];
self.hide_slide(slide);
self.slide_number = newslidenum;
slide = self.slides[self.slide_number];
self.show_slide(slide);
self.set_location();
}
}
else if (this.target == null)
location.href = this.href;
this.blur();
self.disable_slide_click = true;
};
var anchors = document.body.getElementsByTagName("a");
for (var i = 0; i < anchors.length; ++i)
{
if (window.addEventListener)
anchors[i].addEventListener("click", handler, false);
else
anchors[i].attachEvent("onclick", handler);
}
},
// ### CHECK ME ### see which functions are invoked via setTimeout
// either directly or indirectly for use of w3c_slidy vs this
show_slide_number: function () {
var timer = w3c_slidy.get_timer();
w3c_slidy.slide_number_element.innerHTML = timer + "slide".localize() + " " +
(w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length;
},
// every 200mS check if the location has been changed as a
// result of the user activating the Back button/menu item
// doesn't work for Opera < 9.5
check_location: function () {
var hash = location.hash;
if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#"))
w3c_slidy.goto_slide(0);
else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")")
{
var num = parseInt(location.hash.substr(2));
if (!isNaN(num))
w3c_slidy.goto_slide(num-1);
}
if (w3c_slidy.time_left && w3c_slidy.slide_number > 0)
{
w3c_slidy.show_slide_number();
if (w3c_slidy.time_left > 0)
w3c_slidy.time_left -= 200;
}
},
get_timer: function () {
var timer = "";
if (w3c_slidy.time_left)
{
var mins, secs;
secs = Math.floor(w3c_slidy.time_left/1000);
mins = Math.floor(secs / 60);
secs = secs % 60;
timer = (mins ? mins+"m" : "") + secs + "s ";
}
return timer;
},
// this doesn't push location onto history stack for IE
// for which a hidden iframe hack is needed: load page into
// the iframe with script that set's parent's location.hash
// but that won't work for standalone use unless we can
// create the page dynamically via a javascript: URL
set_location: function () {
var uri = w3c_slidy.page_address(location.href);
var hash = "#(" + (w3c_slidy.slide_number+1) + ")";
if (w3c_slidy.slide_number >= 0)
uri = uri + hash;
if (w3c_slidy.ie && !w3c_slidy.ie8)
w3c_slidy.push_hash(hash);
if (uri != location.href) // && !khtml
location.href = uri;
if (this.khtml)
hash = "(" + (w3c_slidy.slide_number+1) + ")";
if (!this.ie && location.hash != hash && location.hash != "")
location.hash = hash;
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide_number();
},
page_address: function (uri) {
var i = uri.indexOf("#");
if (i < 0)
i = uri.indexOf("%23");
// check if anchor is entire page
if (i < 0)
return uri; // yes
return uri.substr(0, i);
},
// only used for IE6 and IE7
on_frame_loaded: function (hash) {
location.hash = hash;
var uri = w3c_slidy.page_address(location.href);
location.href = uri + hash;
},
// history hack with thanks to Bertrand Le Roy
push_hash: function (hash) {
if (hash == "") hash = "#(1)";
window.location.hash = hash;
var doc = document.getElementById("historyFrame").contentWindow.document;
doc.open("javascript:'<html></html>'");
// PWL modified this string literal to break the close script tag
// which otherwise gets parsed when incorporated
doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+
(hash) + "');</" + "script></head><body>hello mum</body></html>");
doc.close();
},
// find current slide based upon location
// first find target anchor and then look
// for associated div element enclosing it
// finally map that to slide number
find_slide_number: function (uri) {
// first get anchor from page location
var i = uri.indexOf("#");
// check if anchor is entire page
if (i < 0)
return 0; // yes
var anchor = unescape(uri.substr(i+1));
// now use anchor as XML ID to find target
var target = document.getElementById(anchor);
if (!target)
{
// does anchor look like "(2)" for slide 2 ??
// where first slide is (1)
var re = /\((\d)+\)/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// accept [2] for backwards compatibility
re = /\[(\d)+\]/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// oh dear unknown anchor
return 0;
}
// search for enclosing slide
while (true)
{
// browser coerces html elements to uppercase!
if (target.nodeName.toLowerCase() == "div" &&
this.has_class(target, "slide"))
{
// found the slide element
break;
}
// otherwise try parent element if any
target = target.parentNode;
if (!target)
{
return 0; // no luck!
}
};
for (i = 0; i < slides.length; ++i)
{
if (slides[i] == target)
return i; // success
}
// oh dear still no luck
return 0;
},
previous_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide;
if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null)
{
w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown);
w3c_slidy.set_eos_status(false);
}
else if (w3c_slidy.slide_number > 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.set_eos_status(true);
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_location();
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
next_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide, last = w3c_slidy.last_shown;
if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1)
w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown);
if ((!incremental || w3c_slidy.last_shown == null) &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number + 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
else if (!w3c_slidy.last_shown)
{
if (last && incremental)
w3c_slidy.last_shown = last;
}
w3c_slidy.set_location();
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
// to first slide with nothing revealed
// i.e. state at start of presentation
first_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
if (w3c_slidy.slide_number != 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = 0;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_eos_status(
!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.set_location();
}
},
// goto last slide with everything revealed
// i.e. state at end of presentation
last_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
w3c_slidy.last_shown = null; //revealNextItem(lastShown);
if (w3c_slidy.last_shown == null &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slides.length - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.show_slide(slide);
}
else
{
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
}
w3c_slidy.set_eos_status(true);
w3c_slidy.set_location();
}
},
// ### check this and consider add/remove class
set_eos_status: function (state) {
if (this.eos)
this.eos.style.color = (state ? "rgb(240,240,240)" : "red");
},
// first slide is 0
goto_slide: function (num) {
//alert("going to slide " + (num+1));
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = num;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide(slide);
w3c_slidy.show_slide_number();
},
show_slide: function (slide) {
this.sync_background(slide);
window.scrollTo(0,0);
this.remove_class(slide, "hidden");
},
hide_slide: function (slide) {
this.add_class(slide, "hidden");
},
// show just the backgrounds pertinent to this slide
// when slide background-color is transparent
// this should now work with rgba color values
sync_background: function (slide) {
var background;
var bgColor;
if (slide.currentStyle)
bgColor = slide.currentStyle["backgroundColor"];
else if (document.defaultView)
{
var styles = document.defaultView.getComputedStyle(slide,null);
if (styles)
bgColor = styles.getPropertyValue("background-color");
else // broken implementation probably due Safari or Konqueror
{
//alert("defective implementation of getComputedStyle()");
bgColor = "transparent";
}
}
else
bgColor == "transparent";
if (bgColor == "transparent" ||
bgColor.indexOf("rgba") >= 0 ||
bgColor.indexOf("opacity") >= 0)
{
var slideClass = this.get_class_list(slide);
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
var bgClass = this.get_class_list(background);
if (this.matching_background(slideClass, bgClass))
this.remove_class(background, "hidden");
else
this.add_class(background, "hidden");
}
}
else // forcibly hide all backgrounds
this.hide_backgrounds();
},
hide_backgrounds: function () {
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
this.add_class(background, "hidden");
}
},
// compare classes for slide and background
matching_background: function (slideClass, bgClass) {
var i, count, pattern, result;
// define pattern as regular expression
pattern = /\w+/g;
// check background class names
result = bgClass.match(pattern);
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (result[i] == "background")
continue;
++count;
}
if (count == 0) // default match
return true;
// check for matches and place result in array
result = slideClass.match(pattern);
// now check if desired name is present for background
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (this.has_token(bgClass, result[i]))
return true;
}
return false;
},
resized: function () {
var width = 0;
if ( typeof( window.innerWidth ) == 'number' )
width = window.innerWidth; // Non IE browser
else if (document.documentElement && document.documentElement.clientWidth)
width = document.documentElement.clientWidth; // IE6
else if (document.body && document.body.clientWidth)
width = document.body.clientWidth; // IE4
var height = 0;
if ( typeof( window.innerHeight ) == 'number' )
height = window.innerHeight; // Non IE browser
else if (document.documentElement && document.documentElement.clientHeight)
height = document.documentElement.clientHeight; // IE6
else if (document.body && document.body.clientHeight)
height = document.body.clientHeight; // IE4
if (height && (width/height > 1.05*1024/768))
{
width = height * 1024.0/768;
}
// IE fires onresize even when only font size is changed!
// so we do a check to avoid blocking < and > actions
if (width != w3c_slidy.last_width || height != w3c_slidy.last_height)
{
if (width >= 1100)
w3c_slidy.size_index = 5; // 4
else if (width >= 1000)
w3c_slidy.size_index = 4; // 3
else if (width >= 800)
w3c_slidy.size_index = 3; // 2
else if (width >= 600)
w3c_slidy.size_index = 2; // 1
else if (width)
w3c_slidy.size_index = 0;
// add in font size adjustment from meta element e.g.
// <meta name="font-size-adjustment" content="-2" />
// useful when slides have too much content ;-)
if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment &&
w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length)
w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment;
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
w3c_slidy.adjust_object_dimensions(width, height);
if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index])
{
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
}
w3c_slidy.last_width = width;
w3c_slidy.last_height = height;
// force reflow to work around Mozilla bug
if (w3c_slidy.ns_pos)
{
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
}
// force correct positioning of toolbar
w3c_slidy.refresh_toolbar(200);
}
},
scrolled: function () {
if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset();
// hide toolbar
w3c_slidy.toolbar.style.display = "none";
// make it reappear later
if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all)
{
setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000);
w3c_slidy.scrollhack = 1;
}
}
},
hide_toolbar: function () {
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden");
window.focus();
},
// used to ensure IE refreshes toolbar in correct position
refresh_toolbar: function (interval) {
if (!w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hide_toolbar();
setTimeout(function () {w3c_slidy.show_toolbar(); }, interval);
}
},
// restores toolbar after short delay
show_toolbar: function () {
if (w3c_slidy.want_toolbar)
{
w3c_slidy.toolbar.style.display = "block";
if (!w3c_slidy.ns_pos)
{
// adjust position to allow for scrolling
var xoffset = w3c_slidy.scroll_x_offset();
w3c_slidy.toolbar.style.left = xoffset;
w3c_slidy.toolbar.style.right = xoffset;
// determine vertical scroll offset
//var yoffset = scrollYOffset();
// bottom is doc height - window height - scroll offset
//var bottom = documentHeight() - lastHeight - yoffset
//if (yoffset > 0 || documentHeight() > lastHeight)
// bottom += 16; // allow for height of scrollbar
w3c_slidy.toolbar.style.bottom = 0; //bottom;
}
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden");
}
w3c_slidy.scrollhack = 0;
// set the keyboard focus to the help link on the
// toolbar to ensure that document has the focus
// IE doesn't always work with window.focus()
// and this hack has benefit of Enter for help
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
},
// invoked via F key
toggle_toolbar: function () {
if (!w3c_slidy.view_all)
{
if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden"))
{
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 1;
}
else
{
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 0;
}
}
},
scroll_x_offset: function () {
if (window.pageXOffset)
return self.pageXOffset;
if (document.documentElement &&
document.documentElement.scrollLeft)
return document.documentElement.scrollLeft;
if (document.body)
return document.body.scrollLeft;
return 0;
},
scroll_y_offset: function () {
if (window.pageYOffset)
return self.pageYOffset;
if (document.documentElement &&
document.documentElement.scrollTop)
return document.documentElement.scrollTop;
if (document.body)
return document.body.scrollTop;
return 0;
},
// looking for a way to determine height of slide content
// the slide itself is set to the height of the window
optimize_font_size: function () {
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
//var dh = documentHeight(); //getDocHeight(document);
var dh = slide.scrollHeight;
var wh = getWindowHeight();
var u = 100 * dh / wh;
alert("window utilization = " + u + "% (doc "
+ dh + " win " + wh + ")");
},
// from document object
get_doc_height: function (doc) {
if (!doc)
doc = document;
if (doc && doc.body && doc.body.offsetHeight)
return doc.body.offsetHeight; // ns/gecko syntax
if (doc && doc.body && doc.body.scrollHeight)
return doc.body.scrollHeight;
alert("couldn't determine document height");
},
get_window_height: function () {
if ( typeof( window.innerHeight ) == 'number' )
return window.innerHeight; // Non IE browser
if (document.documentElement && document.documentElement.clientHeight)
return document.documentElement.clientHeight; // IE6
if (document.body && document.body.clientHeight)
return document.body.clientHeight; // IE4
},
document_height: function () {
var sh, oh;
sh = document.body.scrollHeight;
oh = document.body.offsetHeight;
if (sh && oh)
{
return (sh > oh ? sh : oh);
}
// no idea!
return 0;
},
smaller: function () {
if (w3c_slidy.size_index > 0)
{
--w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
bigger: function () {
if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1)
{
++w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
// with thanks to Ivan Herman for the suggestion
adjust_object_dimensions: function (width, height) {
for( var i = 0; i < w3c_slidy.objects.length; i++ )
{
var obj = this.objects[i];
var mimeType = obj.getAttribute("type");
if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
{
if ( !obj.initialWidth )
obj.initialWidth = obj.getAttribute("width");
if ( !obj.initialHeight )
obj.initialHeight = obj.getAttribute("height");
if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
{
var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
var newW = width * (w/100.0);
obj.setAttribute("width",newW);
}
if ( obj.initialHeight &&
obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
{
var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
var newH = height * (h/100.0);
obj.setAttribute("height", newH);
}
}
}
},
// needed for Opera to inhibit default behavior
// since Opera delivers keyPress even if keyDown
// was cancelled
key_press: function (event) {
if (!event)
event = window.event;
if (!w3c_slidy.key_wanted)
return w3c_slidy.cancel(event);
return true;
},
// See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
key_down: function (event) {
var key;
w3c_slidy.key_wanted = true;
if (!event)
event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey || event.metaKey)
return true;
// dismiss table of contents if visible
if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40)
{
w3c_slidy.hide_table_of_contents();
if (key == 27 || key == 84 || key == 67)
return w3c_slidy.cancel(event);
}
if (key == 34) // Page Down
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.next_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 33) // Page Up
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.previous_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 32) // space bar
{
w3c_slidy.next_slide(true);
return w3c_slidy.cancel(event);
}
else if (key == 37) // Left arrow
{
w3c_slidy.previous_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 36) // Home
{
w3c_slidy.first_slide();
return w3c_slidy.cancel(event);
}
else if (key == 35) // End
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 39) // Right arrow
{
w3c_slidy.next_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 13) // Enter
{
if (w3c_slidy.outline)
{
if (w3c_slidy.outline.visible)
w3c_slidy.fold(w3c_slidy.outline);
else
w3c_slidy.unfold(w3c_slidy.outline);
return w3c_slidy.cancel(event);
}
}
else if (key == 188) // < for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 190) // > for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 189 || key == 109) // - for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 83) // S for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 66) // B for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 90) // Z for last slide
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 70) // F for toggle toolbar
{
w3c_slidy.toggle_toolbar();
return w3c_slidy.cancel(event);
}
else if (key == 65) // A for toggle view single/all slides
{
w3c_slidy.toggle_view();
return w3c_slidy.cancel(event);
}
else if (key == 75) // toggle action of left click for next page
{
w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled;
var alert_msg = (w3c_slidy.mouse_click_enabled ?
"enabled" : "disabled") + " mouse click advance";
alert(alert_msg.localize());
return w3c_slidy.cancel(event);
}
else if (key == 84 || key == 67) // T or C for table of contents
{
if (w3c_slidy.toc)
w3c_slidy.toggle_table_of_contents();
return w3c_slidy.cancel(event);
}
else if (key == 72) // H for help
{
window.location = w3c_slidy.help_page;
return w3c_slidy.cancel(event);
}
//else alert("key code is "+ key);
return true;
},
// safe for both text/html and application/xhtml+xml
create_element: function (name) {
if (this.xhtml && (typeof document.createElementNS != 'undefined'))
return document.createElementNS("http://www.w3.org/1999/xhtml", name)
return document.createElement(name);
},
get_element_style: function (elem, IEStyleProp, CSSStyleProp) {
if (elem.currentStyle)
{
return elem.currentStyle[IEStyleProp];
}
else if (window.getComputedStyle)
{
var compStyle = window.getComputedStyle(elem, "");
return compStyle.getPropertyValue(CSSStyleProp);
}
return "";
},
// the string str is a whitespace separated list of tokens
// test if str contains a particular token, e.g. "slide"
has_token: function (str, token) {
if (str)
{
// define pattern as regular expression
var pattern = /\w+/g;
// check for matches
// place result in array
var result = str.match(pattern);
// now check if desired token is present
for (var i = 0; i < result.length; i++)
{
if (result[i] == token)
return true;
}
}
return false;
},
get_class_list: function (element) {
if (typeof element.className != 'undefined')
return element.className;
return element.getAttribute("class");
},
has_class: function (element, name) {
if (element.nodeType != 1)
return false;
var regexp = new RegExp("(^| )" + name + "\W*");
if (typeof element.className != 'undefined')
return regexp.test(element.className);
return regexp.test(element.getAttribute("class"));
},
remove_class: function (element, name) {
var regexp = new RegExp("(^| )" + name + "\W*");
var clsval = "";
if (typeof element.className != 'undefined')
{
clsval = element.className;
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.className = clsval;
}
}
else
{
clsval = element.getAttribute("class");
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.setAttribute("class", clsval);
}
}
},
add_class: function (element, name) {
if (!this.has_class(element, name))
{
if (typeof element.className != 'undefined')
element.className += " " + name;
else
{
var clsval = element.getAttribute("class");
clsval = clsval ? clsval + " " + name : name;
element.setAttribute("class", clsval);
}
}
},
// HTML elements that can be used with class="incremental"
// note that you can also put the class on containers like
// up, ol, dl, and div to make their contents appear
// incrementally. Upper case is used since this is what
// browsers report for HTML node names (text/html).
incremental_elements: null,
okay_for_incremental: function (name) {
if (!this.incremental_elements)
{
var inclist = new Array();
inclist["p"] = true;
inclist["pre"] = true;
inclist["li"] = true;
inclist["blockquote"] = true;
inclist["dt"] = true;
inclist["dd"] = true;
inclist["h2"] = true;
inclist["h3"] = true;
inclist["h4"] = true;
inclist["h5"] = true;
inclist["h6"] = true;
inclist["span"] = true;
inclist["address"] = true;
inclist["table"] = true;
inclist["tr"] = true;
inclist["th"] = true;
inclist["td"] = true;
inclist["img"] = true;
inclist["object"] = true;
this.incremental_elements = inclist;
}
return this.incremental_elements[name.toLowerCase()];
},
next_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.next_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1) // ELEMENT
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
previous_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.previous_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1)
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
// set visibility for all elements on current slide with
// a parent element with attribute class="incremental"
set_visibility_all_incremental: function (value) {
var node = this.next_incremental_item(null);
if (value == "hidden")
{
while (node)
{
w3c_slidy.add_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
else // value == "visible"
{
while (node)
{
w3c_slidy.remove_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
},
// reveal the next hidden item on the slide
// node is null or the node that was last revealed
reveal_next_item: function (node) {
node = w3c_slidy.next_incremental_item(node);
if (node && node.nodeType == 1) // an element
w3c_slidy.remove_class(node, "invisible");
return node;
},
// exact inverse of revealNextItem(node)
hide_previous_item: function (node) {
if (node && node.nodeType == 1) // an element
w3c_slidy.add_class(node, "invisible");
return this.previous_incremental_item(node);
},
// left to right traversal of root's content
next_node: function (root, node) {
if (node == null)
return root.firstChild;
if (node.firstChild)
return node.firstChild;
if (node.nextSibling)
return node.nextSibling;
for (;;)
{
node = node.parentNode;
if (!node || node == root)
break;
if (node && node.nextSibling)
return node.nextSibling;
}
return null;
},
// right to left traversal of root's content
previous_node: function (root, node) {
if (node == null)
{
node = root.lastChild;
if (node)
{
while (node.lastChild)
node = node.lastChild;
}
return node;
}
if (node.previousSibling)
{
node = node.previousSibling;
while (node.lastChild)
node = node.lastChild;
return node;
}
if (node.parentNode != root)
return node.parentNode;
return null;
},
previous_sibling_element: function (el) {
el = el.previousSibling;
while (el && el.nodeType != 1)
el = el.previousSibling;
return el;
},
next_sibling_element: function (el) {
el = el.nextSibling;
while (el && el.nodeType != 1)
el = el.nextSibling;
return el;
},
first_child_element: function (el) {
var node;
for (node = el.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1)
break;
}
return node;
},
first_tag: function (element, tag) {
var node;
if (!this.is_xhtml)
tag = tag.toUpperCase();
for (node = element.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1 && node.nodeName == tag)
break;
}
return node;
},
hide_selection: function () {
if (window.getSelection) // Firefox, Chromium, Safari, Opera
{
var selection = window.getSelection();
if (selection.rangeCount > 0)
{
var range = selection.getRangeAt(0);
range.collapse (false);
}
}
else // Internet Explorer
{
var textRange = document.selection.createRange ();
textRange.collapse (false);
}
},
get_selected_text: function () {
try
{
if (window.getSelection)
return window.getSelection().toString();
if (document.getSelection)
return document.getSelection().toString();
if (document.selection)
return document.selection.createRange().text;
}
catch (e)
{
}
return "";
},
// make note of length of selected text
// as this evaluates to zero in click event
mouse_button_up: function (e) {
w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length;
},
// right mouse button click is reserved for context menus
// it is more reliable to detect rightclick than leftclick
mouse_button_click: function (e) {
var rightclick = false;
var leftclick = false;
var middleclick = false;
var target;
if (!e)
var e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target.nodeType == 3)
target = target.parentNode;
if (e.which) // all browsers except IE
{
leftclick = (e.which == 1);
middleclick = (e.which == 2);
rightclick = (e.which == 3);
}
else if (e.button)
{
// Konqueror gives 1 for left, 4 for middle
// IE6 gives 0 for left and not 1 as I expected
if (e.button == 4)
middleclick = true;
// all browsers agree on 2 for right button
rightclick = (e.button == 2);
}
else leftclick = true;
/*
alert("you clicked over a " + target.nodeName + " element\n" +
"w3c_slidy.mouse_click_enabled = " + w3c_slidy.mouse_click_enabled + "\n" +
"leftclick = " + leftclick + "\n" +
"selected text length = " + w3c_slidy.selected_text_len);
//alert("selected text length = " + w3c_slidy.selected_text_len);
*/
if (w3c_slidy.selected_text_len > 0)
{
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
// dismiss table of contents
w3c_slidy.hide_table_of_contents();
// check if target is something that probably want's clicks
// e.g. a, embed, object, input, textarea, select, option
var tag = target.nodeName.toLowerCase();
if (w3c_slidy.mouse_click_enabled && leftclick &&
tag != "a" &&
tag != "embed" &&
tag != "object" &&
tag != "video" &&
tag != "input" &&
tag != "textarea" &&
tag != "select" &&
tag != "option" &&
!target.onclick)
{
w3c_slidy.next_slide(true);
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
},
get_key: function (e)
{
var key;
// kludge around NS/IE differences
if (typeof window.event != "undefined")
key = window.event.keyCode;
else if (e.which)
key = e.which;
return key;
},
get_target: function (e) {
var target;
if (!e)
e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
if (target.nodeType != 1)
target = target.parentNode;
return target;
},
// does display property provide correct defaults?
is_block: function (elem) {
var tag = elem.nodeName.toLowerCase();
return tag == "ol" || tag == "ul" || tag == "p" ||
tag == "li" || tag == "table" || tag == "pre" ||
tag == "h1" || tag == "h2" || tag == "h3" ||
tag == "h4" || tag == "h5" || tag == "h6" ||
tag == "blockquote" || tag == "address";
},
add_listener: function (element, event, handler) {
if (window.addEventListener)
element.addEventListener(event, handler, false);
else
element.attachEvent("on"+event, handler);
},
// used to prevent event propagation from field controls
stop_propagation: function (event) {
event = event ? event : window.event;
event.cancelBubble = true; // for IE
if (event.stopPropagation)
event.stopPropagation();
return true;
},
cancel: function (event) {
if (event)
{
event.cancel = true;
event.returnValue = false;
if (event.preventDefault)
event.preventDefault();
}
w3c_slidy.key_wanted = false;
return false;
}
};
// for each language define an associative array
// and also the help text which is longer
var w3c_slidy_i18n = {
strings_es: {
"slide":"pág.",
"help?":"Ayuda",
"contents?":"Índice",
"table of contents":"tabla de contenidos",
"Table of Contents":"Tabla de Contenidos",
"restart presentation":"Reiniciar presentación",
"restart?":"Inicio"
},
help_es:
"Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
"o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.",
strings_ca: {
"slide":"pàg..",
"help?":"Ajuda",
"contents?":"Índex",
"table of contents":"taula de continguts",
"Table of Contents":"Taula de Continguts",
"restart presentation":"Reiniciar presentació",
"restart?":"Inici"
},
help_ca:
"Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
"o Re pàg y Av pàg. Usi S i B per canviar grandària de font.",
strings_cs: {
"slide":"snímek",
"help?":"nápověda",
"contents?":"obsah",
"table of contents":"obsah prezentace",
"Table of Contents":"Obsah prezentace",
"restart presentation":"znovu spustit prezentaci",
"restart?":"restart"
},
help_cs:
"Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " +
"šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " +
"dá zvětšit a zmenšit pomocí kláves B a S.",
strings_nl: {
"slide":"pagina",
"help?":"Help?",
"contents?":"Inhoud?",
"table of contents":"inhoudsopgave",
"Table of Contents":"Inhoudsopgave",
"restart presentation":"herstart presentatie",
"restart?":"Herstart?"
},
help_nl:
"Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
"of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.",
strings_de: {
"slide":"Seite",
"help?":"Hilfe",
"contents?":"Übersicht",
"table of contents":"Inhaltsverzeichnis",
"Table of Contents":"Inhaltsverzeichnis",
"restart presentation":"Präsentation neu starten",
"restart?":"Neustart"
},
help_de:
"Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
"Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.",
strings_pl: {
"slide":"slajd",
"help?":"pomoc?",
"contents?":"spis treści?",
"table of contents":"spis treści",
"Table of Contents":"Spis Treści",
"restart presentation":"Restartuj prezentację",
"restart?":"restart?"
},
help_pl:
"Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
"lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.",
strings_fr: {
"slide":"page",
"help?":"Aide",
"contents?":"Index",
"table of contents":"table des matières",
"Table of Contents":"Table des matières",
"restart presentation":"Recommencer l'exposé",
"restart?":"Début"
},
help_fr:
"Naviguez avec la souris, la barre d'espace, les flèches " +
"gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
"les touches S et B pour modifier la taille de la police.",
strings_hu: {
"slide":"oldal",
"help?":"segítség",
"contents?":"tartalom",
"table of contents":"tartalomjegyzék",
"Table of Contents":"Tartalomjegyzék",
"restart presentation":"bemutató újraindítása",
"restart?":"újraindítás"
},
help_hu:
"Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
"használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
"Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
"a szöveg méretét.",
strings_it: {
"slide":"pag.",
"help?":"Aiuto",
"contents?":"Indice",
"table of contents":"indice",
"Table of Contents":"Indice",
"restart presentation":"Ricominciare la presentazione",
"restart?":"Inizio"
},
help_it:
"Navigare con mouse, barra spazio, frecce sinistra/destra o " +
"PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.",
strings_el: {
"slide":"σελίδα",
"help?":"βοήθεια;",
"contents?":"περιεχόμενα;",
"table of contents":"πίνακας περιεχομένων",
"Table of Contents":"Πίνακας Περιεχομένων",
"restart presentation":"επανεκκίνηση παρουσίασης",
"restart?":"επανεκκίνηση;"
},
help_el:
"Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
"ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
"το μέγεθος της γραμματοσειράς.",
strings_ja: {
"slide":"スライド",
"help?":"ヘルプ",
"contents?":"目次",
"table of contents":"目次を表示",
"Table of Contents":"目次",
"restart presentation":"最初から再生",
"restart?":"最初から"
},
help_ja:
"マウス左クリック ・ スペース ・ 左右キー " +
"または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更",
strings_zh: {
"slide":"幻灯片",
"help?":"帮助?",
"contents?":"内容?",
"table of contents":"目录",
"Table of Contents":"目录",
"restart presentation":"重新启动展示",
"restart?":"重新启动?"
},
help_zh:
"用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
"用 S, B 改变字体大小.",
strings_ru: {
"slide":"слайд",
"help?":"помощь?",
"contents?":"содержание?",
"table of contents":"оглавление",
"Table of Contents":"Оглавление",
"restart presentation":"перезапустить презентацию",
"restart?":"перезапуск?"
},
help_ru:
"Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
"влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.",
strings_sv: {
"slide":"sida",
"help?":"hjälp",
"contents?":"innehåll",
"table of contents":"innehållsförteckning",
"Table of Contents":"Innehållsförteckning",
"restart presentation":"visa presentationen från början",
"restart?":"börja om"
},
help_sv:
"Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " +
"vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " +
"Använd tangenterna S och B för att ändra textens storlek.",
// each such language array is declared in the localize array
// which is set on string prototype and used as in "foo".localize();
localize: {
"es":this.strings_es,
"ca":this.strings_ca,
"cs":this.strings_cs,
"nl":this.strings_nl,
"de":this.strings_de,
"pl":this.strings_pl,
"fr":this.strings_fr,
"hu":this.strings_hu,
"it":this.strings_it,
"el":this.strings_el,
"jp":this.strings_ja,
"zh":this.strings_zh,
"ru":this.strings_ru,
"sv":this.strings_sv
},
init: function () {
var i18n = w3c_slidy_i18n;
var help_text = w3c_slidy.help_text;
i18n.strings_es[help_text] = i18n.help_es;
i18n.strings_ca[help_text] = i18n.help_ca;
i18n.strings_cs[help_text] = i18n.help_cs;
i18n.strings_nl[help_text] = i18n.help_nl;
i18n.strings_de[help_text] = i18n.help_de;
i18n.strings_pl[help_text] = i18n.help_pl;
i18n.strings_fr[help_text] = i18n.help_fr;
i18n.strings_hu[help_text] = i18n.help_hu;
i18n.strings_it[help_text] = i18n.help_it;
i18n.strings_el[help_text] = i18n.help_el;
i18n.strings_ja[help_text] = i18n.help_ja;
i18n.strings_zh[help_text] = i18n.help_zh;
i18n.strings_ru[help_text] = i18n.help_ru;
i18n.strings_sv[help_text] = i18n.help_sv;
w3c_slidy.lang = document.body.parentNode.getAttribute("lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = "en";
// add localize method to all strings
// for use as in "contents".localize()
String.prototype.localize = function() {
if (this == "")
return this;
// try full language code, e.g. en-US
var s, lookup = w3c_slidy_i18n.localize[w3c_slidy.lang];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
// strip country code suffix, e.g.
// try en if undefined for en-US
var lg = w3c_slidy.lang.split("-");
if (lg.length > 1)
{
lookup = w3c_slidy_i18n.localize[lg[0]];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
}
// otherwise string as is
return this;
};
}
};
// hack for back button behavior
if (w3c_slidy.ie6 || w3c_slidy.ie7)
{
document.write("<iframe id='historyFrame' " +
"src='javascript:\"<html"+"></"+"html>\"' " +
"height='1' width='1' " +
"style='position:absolute;left:-800px'></iframe>");
}
// attach event listeners for initialization
w3c_slidy.set_up();
// hide the slides as soon as body element is available
// to reduce annoying screen mess before the onload event
setTimeout(w3c_slidy.hide_slides, 50);
/*]]>*/
</script>
</head>
<body class="article">
<div id="header" class="slide">
<h1>JavaScript II - Objects, Arrays and Booleans</h1>
<span id="author">Bruce Harris, 8/2/12</span><br />
</div>
<div class="sect1 slide">
<h1 id="_content_and_target_audience">Content and target audience</h1>
<div class="sectionbody">
<div class="paragraph"><p><strong>JavaScript II - Objects, Arrays, and Booleans</strong></p></div>
<div class="paragraph"><p>Laying the foundation for object oriented programing in JavaScript.</p></div>
<div class="paragraph"><p>Constructor functions, prototypes, the <tt>this</tt> keyword, object inheritance
and other related topics will be covered in later talks.</p></div>
<div class="paragraph"><p>Emphasis on behavior/syntax specific to JavaScript (as compared to other languages).</p></div>
<div class="paragraph"><p>You are familiar with basics of functional programming in JavaScript
(covered in <a href="http://bruceharris.net/techtalks">JavaScript I - Variables, Functions, and Scope</a>)</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_resources_and_tools">Resources and tools</h1>
<div class="sectionbody">
<ul class="">
<li>
<span>
These slides: <a href="http://bruceharris.net/techtalks/">http://bruceharris.net/techtalks</a>
</span>
</li>
<li>
<span>
Sandboxes: <a href="http://codepen.io/pen">CodePen</a>, <a href="http://jsfiddle.net/">JSFiddle</a>, <a href="http://jsbin.com/">JS Bin</a>
</span>
</li>
<li>
<span>
Use your browser&#8217;s debugger / developer tools
</span>
</li>
<li>
<span>
Reference: <a href="https://developer.mozilla.org/en/JavaScript/">Mozilla Developer Network</a>
</span>
</li>
<li>
<span>
Instruction (online book): <a href="http://eloquentjavascript.net/contents.html">Eloquent JavaScript</a>
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_not_as_i_do_8230">Not as I do&#8230;</h1>
<div class="sectionbody">
<div class="paragraph"><p>Avoid <tt>document.writeln()</tt> - not useful in real life, but useful for examples</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_object_literals">Object literals</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">customer</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">account</span><span class="o">:</span> <span class="mi">1003</span><span class="p">,</span>
<span class="nx">name</span><span class="o">:</span> <span class="s2">&quot;Rick Danko&quot;</span>
<span class="p">};</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_accessing_properties">Accessing properties</h1>
<div class="sectionbody">
<div class="paragraph"><p>Both bracket notatation and dot notation can be used to access properties</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">[</span><span class="s1">&#39;account&#39;</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">.</span><span class="nx">account</span> <span class="o">==</span> <span class="nx">customer</span><span class="p">[</span><span class="s1">&#39;account&#39;</span><span class="p">]);</span>
<span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="s2">&quot;name&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">[</span><span class="nx">p</span><span class="p">]);</span> <span class="c1">// can we do this?</span>
<span class="nx">p</span> <span class="o">=</span> <span class="s2">&quot;account&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">[</span><span class="nx">p</span><span class="p">]);</span> <span class="c1">// can we do this?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_adding_properties_to_an_object">Adding properties to an object</h1>
<div class="sectionbody">
<div class="paragraph"><p>Both bracket notatation and dot notation can be used to assign/add properties</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">customer</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">customer</span><span class="p">.</span><span class="nx">account</span> <span class="o">=</span> <span class="mi">1003</span><span class="p">;</span>
<span class="nx">customer</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;Rick Danko&quot;</span><span class="p">;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_deleting_properties">Deleting properties</h1>
<div class="sectionbody">
<div class="paragraph"><p>The <tt>delete</tt> keyword</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">customer</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">account</span><span class="o">:</span> <span class="mi">1003</span><span class="p">,</span>
<span class="nx">name</span><span class="o">:</span> <span class="s2">&quot;Rick Danko&quot;</span>
<span class="p">};</span>
<span class="k">delete</span> <span class="nx">customer</span><span class="p">.</span><span class="nx">account</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span> <span class="c1">// ?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_accessing_properties_of_an_object_literal">Accessing properties of an object literal</h1>
<div class="sectionbody">
<div class="paragraph"><p>Parentheses required</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">numberToText</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span>
<span class="k">return</span> <span class="p">({</span>
<span class="mi">1</span><span class="o">:</span> <span class="s1">&#39;one&#39;</span><span class="p">,</span>
<span class="mi">2</span><span class="o">:</span> <span class="s1">&#39;two&#39;</span>
<span class="c1">// ...</span>
<span class="p">})[</span><span class="nx">num</span><span class="p">];</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">numberToText</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">numberToText</span><span class="p">(</span><span class="mi">3</span><span class="p">));</span> <span class="c1">// ?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_property_names">Property names</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;var&quot;</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="c1">// Can we use JavaScript keywords?</span>
<span class="s2">&quot;+&quot;</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span> <span class="c1">// Symbols?</span>
<span class="s2">&quot;fat black cat&quot;</span><span class="o">:</span> <span class="mi">4</span> <span class="c1">// Spaces?</span>
<span class="p">};</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Yes, with 2 caveats</p></div>
<ul class=" incremental">
<li>
<span>
Wrap property names in quotes in object literals
</span>
</li>
<li>
<span>
Use bracket notation, not <em>dot</em> notation, to access or assign properties
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_methods">Methods</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">f</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="c1">// can an object property contain a function?</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Yes, functions are first class citizens in JavaScript.
This is how "methods" are implemented in JavaScript.</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_object_tt_type_tt">Object <tt>type</tt></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span><span class="nx">a</span><span class="o">:</span> <span class="mi">1</span><span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">o</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_some_are_more_equal_than_others">Some are more equal than others</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">==</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">===</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">!=</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">!==</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_truthy_and_falsy">"Truthy" and "Falsy"</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">write</span><span class="p">(</span><span class="nx">s</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">write</span><span class="p">(</span><span class="mi">1</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="mi">0</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="s1">&#39;hi&#39;</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="s1">&#39;&#39;</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="s1">&#39;0&#39;</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="kc">null</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="kc">undefined</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span> <span class="p">({}).</span><span class="nx">foo</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_short_circuit_evaluation">Short circuit evaluation</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">bar</span><span class="o">:</span> <span class="s2">&quot;hello&quot;</span><span class="p">,</span>
<span class="nx">baz</span><span class="o">:</span> <span class="mi">0</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">foo</span> <span class="o">||</span> <span class="s2">&quot;o does not have a foo property&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">bar</span> <span class="o">&amp;&amp;</span> <span class="s2">&quot;o.bar has a truthy value&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">baz</span> <span class="o">||</span> <span class="s2">&quot;o.baz has a falsy value&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_in_tt_operator"><tt>in</tt> operator</h1>
<div class="sectionbody">
<div class="paragraph"><p>(<em>string</em> in <em>object</em>) is a boolean expression</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">a</span><span class="o">:</span> <span class="mi">1</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;a&#39;</span> <span class="k">in</span> <span class="nx">o</span><span class="p">);</span> <span class="c1">// does o have a property named a?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;b&#39;</span> <span class="k">in</span> <span class="nx">o</span><span class="p">);</span> <span class="c1">// does o have a property named b?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_in_tt_operator_2"><tt>in</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">a</span><span class="o">:</span> <span class="kc">false</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;a&#39;</span> <span class="k">in</span> <span class="nx">o</span><span class="p">);</span> <span class="c1">// true or false?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_for_8230_in_tt_loop"><tt>for &#8230; in</tt> loop</h1>
<div class="sectionbody">
<div class="paragraph"><p>Enumerates over <em>enumerable</em> properties of an object</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">a</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">b</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">c</span><span class="o">:</span> <span class="mi">3</span>
<span class="p">};</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">o</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s2">&quot;| &quot;</span> <span class="o">+</span> <span class="nx">prop</span> <span class="o">+</span> <span class="s1">&#39;:&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">+</span> <span class="s2">&quot; |&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_the_global_object">The global object</h1>
<div class="sectionbody">
<ul class="">
<li>
<span>
Every JavaScript environment has a single global object
</span>
</li>
<li>
<span>
All global variables are properties of this object
</span>
</li>
<li>
<span>
In web browsers, the global object is <tt>window</tt>
</span>
</li>
</ul>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g1</span> <span class="o">=</span> <span class="s2">&quot;Just an innocent global&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">g1</span> <span class="o">==</span> <span class="nx">g1</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">g2</span> <span class="o">=</span> <span class="s2">&quot;Another global&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">g2</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_accessing_a_shadowed_global">Accessing a "shadowed" global</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">// can we access the global g here?</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_accessing_a_shadowed_global_2">Accessing a "shadowed" global</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">g</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_accessing_shadowed_non_globals">Accessing "shadowed" non-globals?</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="c1">// can we access the &quot;middle&quot; g here?</span>
<span class="p">})();</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Sorry, no</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_array_literals">Array literals</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_mixed_type_arrays">Mixed type arrays</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">14</span><span class="p">,</span> <span class="s2">&quot;shoe&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">a</span><span class="o">:</span> <span class="mi">8</span><span class="p">}];</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mf">3.1415</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">a</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_some_useful_array_methods">Some useful array methods</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;coffee&quot;</span><span class="p">,</span> <span class="s2">&quot;tea&quot;</span><span class="p">,</span> <span class="s2">&quot;beer&quot;</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">join</span><span class="p">());</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot; or &quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;?&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot; please&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">join</span><span class="p">());</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_nested_object_array_structures">Nested object / array structures</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">14</span><span class="p">,</span> <span class="s2">&quot;shoe&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">a</span><span class="o">:</span> <span class="mi">8</span><span class="p">}];</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mf">3.1415</span><span class="p">);</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">b</span><span class="o">:</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="s2">&quot;r&quot;</span><span class="p">]]});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">a</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">4</span><span class="p">][</span><span class="s1">&#39;b&#39;</span><span class="p">][</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_javascript_does_not_have_real_arrays">JavaScript does not have real arrays</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">a</span><span class="p">);</span>
<span class="nx">a</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;huh?&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="k">delete</span> <span class="nx">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="c1">// did array shift to fill in gap left at index 1?</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="s2">&quot;2&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="nx">s</span><span class="p">]);</span> <span class="c1">// can we access array elements with a string index?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_functional_programming_with_arrays">Functional programming with arrays</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">forEach</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">fn</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="nx">fn</span><span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">printPlus1</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">((</span><span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="nx">forEach</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">printPlus1</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_objects_as_namespaces">Objects as namespaces</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">MyApp</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">Module1</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// public functions (methods) and variables (properties)</span>
<span class="p">},</span>
<span class="nx">Module2</span><span class="o">:</span> <span class="p">(</span><span class="kd">function</span><span class="p">(){</span> <span class="c1">// note enclosing parentheses - immediate function</span>
<span class="c1">// private code and variables</span>
<span class="k">return</span> <span class="p">{</span>
<span class="c1">// public properties/methods</span>
<span class="p">};</span>
<span class="p">})(),</span>
<span class="nx">Module3</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="c1">// just a function</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_returning_an_object">Function returning an object</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="nx">account</span><span class="p">,</span> <span class="nx">name</span><span class="p">){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">account</span><span class="o">:</span> <span class="nx">account</span><span class="p">,</span>
<span class="nx">name</span><span class="o">:</span> <span class="nx">name</span>
<span class="p">};</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_objects_with_methods_and_private_variables">Objects with methods and private variables</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCounter</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">reset</span><span class="p">(</span><span class="nx">newCount</span><span class="p">){</span>
<span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">current</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">count</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">reset</span><span class="o">:</span> <span class="nx">reset</span><span class="p">,</span>
<span class="nx">current</span><span class="o">:</span> <span class="nx">current</span><span class="p">,</span>
<span class="nx">increment</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_1">Exercise 1</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">map</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">fn</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">plus1</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">a2</span> <span class="o">=</span> <span class="nx">map</span><span class="p">(</span><span class="nx">a1</span><span class="p">,</span> <span class="nx">plus1</span><span class="p">);</span> <span class="c1">// [22, 33, 26]</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_2">Exercise 2</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">translateNote</span><span class="p">(</span><span class="nx">note</span><span class="p">){</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">note</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="s1">&#39;c&#39;</span><span class="o">:</span>
<span class="k">return</span> <span class="s1">&#39;dough&#39;</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="s1">&#39;d&#39;</span><span class="o">:</span>
<span class="k">return</span> <span class="s1">&#39;ray&#39;</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="k">return</span> <span class="s1">&#39;I only know 2 notes&#39;</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">translateNote</span><span class="p">(</span><span class="s1">&#39;c&#39;</span><span class="p">));</span> <span class="c1">// &#39;dough&#39;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">translateNote</span><span class="p">(</span><span class="s1">&#39;d&#39;</span><span class="p">));</span> <span class="c1">// &#39;ray&#39;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">translateNote</span><span class="p">(</span><span class="s1">&#39;e&#39;</span><span class="p">));</span> <span class="c1">// &#39;I only know 2 notes&#39;</span>
<span class="c1">// rewrite translateNote to use only 1 return statement</span>
<span class="c1">// hint: don&#39;t use switch</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_3">Exercise 3</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">account</span><span class="p">){</span>
<span class="cm">/****</span>
<span class="cm"> your code here</span>
<span class="cm"> customer object has...</span>
<span class="cm"> - a name property containing the customer&#39;s name</span>
<span class="cm"> - an account property containing the customer&#39;s account number</span>
<span class="cm"> - an addOrder method that takes 1 argument: order number</span>
<span class="cm"> - a getOrders method that returns a string containing info about</span>
<span class="cm"> customer&#39;s orders, per below example</span>
<span class="cm"> - info about orders can only be accessed via the getOrders method</span>
<span class="cm"> */</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bob</span> <span class="o">=</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="s1">&#39;Bob&#39;</span><span class="p">,</span> <span class="mi">5673</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">getOrders</span><span class="p">());</span> <span class="c1">// &quot;Bob has no orders&quot;</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90023</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">getOrders</span><span class="p">());</span> <span class="c1">// &quot;Bob&#39;s order: 90023&quot;</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90028</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">getOrders</span><span class="p">());</span> <span class="c1">// &quot;Bob&#39;s orders: 90023, 90028&quot;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_4">Exercise 4</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">reduce</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">fn</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">add</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">+</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">mult</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">*</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">add</span><span class="p">));</span> <span class="c1">// 12</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">mult</span><span class="p">));</span> <span class="c1">// 42</span>
</pre></div></div></div>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="AsciiDoc 8.6.7">
<title>JavaScript II - Objects, Arrays and Booleans</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
pre {
padding: 0;
margin: 0;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
tt {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
.monospaced {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/*
pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = { // Namespace.
/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////
/* Author: Mihai Bazon, September 2002
* http://students.infoiasi.ro/~mishoo
*
* Table Of Content generator
* Version: 0.4
*
* Feel free to use this script under the terms of the GNU General Public
* License, as long as you do not remove or alter this notice.
*/
/* modified by Troy D. Hanson, September 2006. License: GPL */
/* modified by Stuart Rackham, 2006, 2009. License: GPL */
// toclevels = 1..4.
toc: function (toclevels) {
function getText(el) {
var text = "";
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
text += i.data;
else if (i.firstChild != null)
text += getText(i);
}
return text;
}
function TocEntry(el, text, toclevel) {
this.element = el;
this.text = text;
this.toclevel = toclevel;
}
function tocEntries(el, toclevels) {
var result = new Array;
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
// Function that scans the DOM tree for header elements (the DOM2
// nodeIterator API would be a better technique but not supported by all
// browsers).
var iterate = function (el) {
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
var mo = re.exec(i.tagName);
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
}
iterate(i);
}
}
}
iterate(el);
return result;
}
var toc = document.getElementById("toc");
if (!toc) {
return;
}
// Delete existing TOC entries in case we're reloading the TOC.
var tocEntriesToRemove = [];
var i;
for (i = 0; i < toc.childNodes.length; i++) {
var entry = toc.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div'
&& entry.getAttribute("class")
&& entry.getAttribute("class").match(/^toclevel/))
tocEntriesToRemove.push(entry);
}
for (i = 0; i < tocEntriesToRemove.length; i++) {
toc.removeChild(tocEntriesToRemove[i]);
}
// Rebuild TOC entries.
var entries = tocEntries(document.getElementById("content"), toclevels);
for (var i = 0; i < entries.length; ++i) {
var entry = entries[i];
if (entry.element.id == "")
entry.element.id = "_toc_" + i;
var a = document.createElement("a");
a.href = "#" + entry.element.id;
a.appendChild(document.createTextNode(entry.text));
var div = document.createElement("div");
div.appendChild(a);
div.className = "toclevel" + entry.toclevel;
toc.appendChild(div);
}
if (entries.length == 0)
toc.parentNode.removeChild(toc);
},
/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////
/* Based on footnote generation code from:
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
*/
footnotes: function () {
// Delete existing footnote entries in case we're reloading the footnodes.
var i;
var noteholder = document.getElementById("footnotes");
if (!noteholder) {
return;
}
var entriesToRemove = [];
for (i = 0; i < noteholder.childNodes.length; i++) {
var entry = noteholder.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
entriesToRemove.push(entry);
}
for (i = 0; i < entriesToRemove.length; i++) {
noteholder.removeChild(entriesToRemove[i]);
}
// Rebuild footnote entries.
var cont = document.getElementById("content");
var spans = cont.getElementsByTagName("span");
var refs = {};
var n = 0;
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnote") {
n++;
var note = spans[i].getAttribute("data-note");
if (!note) {
// Use [\s\S] in place of . so multi-line matches work.
// Because JavaScript has no s (dotall) regex flag.
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
spans[i].innerHTML =
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
spans[i].setAttribute("data-note", note);
}
noteholder.innerHTML +=
"<div class='footnote' id='_footnote_" + n + "'>" +
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
n + "</a>. " + note + "</div>";
var id =spans[i].getAttribute("id");
if (id != null) refs["#"+id] = n;
}
}
if (n == 0)
noteholder.parentNode.removeChild(noteholder);
else {
// Process footnoterefs.
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnoteref") {
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
href = href.match(/#.*/)[0]; // Because IE return full URL.
n = refs[href];
spans[i].innerHTML =
"[<a href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
}
}
}
},
install: function(toclevels) {
var timerId;
function reinstall() {
asciidoc.footnotes();
if (toclevels) {
asciidoc.toc(toclevels);
}
}
function reinstallAndRemoveTimer() {
clearInterval(timerId);
reinstall();
}
timerId = setInterval(reinstall, 500);
if (document.addEventListener)
document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
else
window.onload = reinstallAndRemoveTimer;
}
}
asciidoc.install();
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>JavaScript II - Objects, Arrays and Booleans</h1>
<span id="author">Bruce Harris, 8/2/12</span><br>
</div>
<div id="content">
<div class="sect1">
<h2 id="_content_and_target_audience">Content and target audience</h2>
<div class="sectionbody">
<div class="paragraph"><p><strong>JavaScript II - Objects, Arrays, and Booleans</strong></p></div>
<div class="paragraph"><p>Laying the foundation for object oriented programing in JavaScript.</p></div>
<div class="paragraph"><p>Constructor functions, prototypes, the <span class="monospaced">this</span> keyword, object inheritance
and other related topics will be covered in later talks.</p></div>
<div class="paragraph"><p>Emphasis on behavior/syntax specific to JavaScript (as compared to other languages).</p></div>
<div class="paragraph"><p>You are familiar with basics of functional programming in JavaScript
(covered in <a href="http://bruceharris.net/techtalks">JavaScript I - Variables, Functions, and Scope</a>)</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_resources_and_tools">Resources and tools</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
These slides: <a href="http://bruceharris.net/techtalks/">http://bruceharris.net/techtalks</a>
</p>
</li>
<li>
<p>
Sandboxes: <a href="http://codepen.io/pen">CodePen</a>, <a href="http://jsfiddle.net/">JSFiddle</a>, <a href="http://jsbin.com/">JS Bin</a>
</p>
</li>
<li>
<p>
Use your browser&#8217;s debugger / developer tools
</p>
</li>
<li>
<p>
Reference: <a href="https://developer.mozilla.org/en/JavaScript/">Mozilla Developer Network</a>
</p>
</li>
<li>
<p>
Instruction (online book): <a href="http://eloquentjavascript.net/contents.html">Eloquent JavaScript</a>
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_not_as_i_do_8230">Not as I do&#8230;</h2>
<div class="sectionbody">
<div class="paragraph"><p>Avoid <span class="monospaced">document.writeln()</span> - not useful in real life, but useful for examples</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_object_literals">Object literals</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">customer</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">account</span><span class="o">:</span> <span class="mi">1003</span><span class="p">,</span>
<span class="nx">name</span><span class="o">:</span> <span class="s2">&quot;Rick Danko&quot;</span>
<span class="p">};</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_accessing_properties">Accessing properties</h2>
<div class="sectionbody">
<div class="paragraph"><p>Both bracket notatation and dot notation can be used to access properties</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">[</span><span class="s1">&#39;account&#39;</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">.</span><span class="nx">account</span> <span class="o">==</span> <span class="nx">customer</span><span class="p">[</span><span class="s1">&#39;account&#39;</span><span class="p">]);</span>
<span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="s2">&quot;name&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">[</span><span class="nx">p</span><span class="p">]);</span> <span class="c1">// can we do this?</span>
<span class="nx">p</span> <span class="o">=</span> <span class="s2">&quot;account&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">[</span><span class="nx">p</span><span class="p">]);</span> <span class="c1">// can we do this?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_adding_properties_to_an_object">Adding properties to an object</h2>
<div class="sectionbody">
<div class="paragraph"><p>Both bracket notatation and dot notation can be used to assign/add properties</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">customer</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">customer</span><span class="p">.</span><span class="nx">account</span> <span class="o">=</span> <span class="mi">1003</span><span class="p">;</span>
<span class="nx">customer</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;Rick Danko&quot;</span><span class="p">;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_deleting_properties">Deleting properties</h2>
<div class="sectionbody">
<div class="paragraph"><p>The <span class="monospaced">delete</span> keyword</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">customer</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">account</span><span class="o">:</span> <span class="mi">1003</span><span class="p">,</span>
<span class="nx">name</span><span class="o">:</span> <span class="s2">&quot;Rick Danko&quot;</span>
<span class="p">};</span>
<span class="k">delete</span> <span class="nx">customer</span><span class="p">.</span><span class="nx">account</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">customer</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span> <span class="c1">// ?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_accessing_properties_of_an_object_literal">Accessing properties of an object literal</h2>
<div class="sectionbody">
<div class="paragraph"><p>Parentheses required</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">numberToText</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span>
<span class="k">return</span> <span class="p">({</span>
<span class="mi">1</span><span class="o">:</span> <span class="s1">&#39;one&#39;</span><span class="p">,</span>
<span class="mi">2</span><span class="o">:</span> <span class="s1">&#39;two&#39;</span>
<span class="c1">// ...</span>
<span class="p">})[</span><span class="nx">num</span><span class="p">];</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">numberToText</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">numberToText</span><span class="p">(</span><span class="mi">3</span><span class="p">));</span> <span class="c1">// ?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_property_names">Property names</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;var&quot;</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span> <span class="c1">// Can we use JavaScript keywords?</span>
<span class="s2">&quot;+&quot;</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span> <span class="c1">// Symbols?</span>
<span class="s2">&quot;fat black cat&quot;</span><span class="o">:</span> <span class="mi">4</span> <span class="c1">// Spaces?</span>
<span class="p">};</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Yes, with 2 caveats</p></div>
<div class="ulist incremental"><ul>
<li>
<p>
Wrap property names in quotes in object literals
</p>
</li>
<li>
<p>
Use bracket notation, not <em>dot</em> notation, to access or assign properties
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_methods">Methods</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">f</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="c1">// can an object property contain a function?</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Yes, functions are first class citizens in JavaScript.
This is how "methods" are implemented in JavaScript.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_object_span_class_monospaced_type_span">Object <span class="monospaced">type</span></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span><span class="nx">a</span><span class="o">:</span> <span class="mi">1</span><span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">o</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_some_are_more_equal_than_others">Some are more equal than others</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">==</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">===</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">!=</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">0</span> <span class="o">!==</span> <span class="s1">&#39;0&#39;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_truthy_and_falsy">"Truthy" and "Falsy"</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">write</span><span class="p">(</span><span class="nx">s</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">write</span><span class="p">(</span><span class="mi">1</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="mi">0</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="s1">&#39;hi&#39;</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="s1">&#39;&#39;</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="s1">&#39;0&#39;</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="kc">null</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span><span class="kc">undefined</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
<span class="nx">write</span><span class="p">(</span> <span class="p">({}).</span><span class="nx">foo</span> <span class="o">?</span> <span class="s1">&#39;yes&#39;</span> <span class="o">:</span> <span class="s1">&#39;no&#39;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_short_circuit_evaluation">Short circuit evaluation</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">bar</span><span class="o">:</span> <span class="s2">&quot;hello&quot;</span><span class="p">,</span>
<span class="nx">baz</span><span class="o">:</span> <span class="mi">0</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">foo</span> <span class="o">||</span> <span class="s2">&quot;o does not have a foo property&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">bar</span> <span class="o">&amp;&amp;</span> <span class="s2">&quot;o.bar has a truthy value&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">baz</span> <span class="o">||</span> <span class="s2">&quot;o.baz has a falsy value&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_span_class_monospaced_in_span_operator"><span class="monospaced">in</span> operator</h2>
<div class="sectionbody">
<div class="paragraph"><p>(<em>string</em> in <em>object</em>) is a boolean expression</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">a</span><span class="o">:</span> <span class="mi">1</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;a&#39;</span> <span class="k">in</span> <span class="nx">o</span><span class="p">);</span> <span class="c1">// does o have a property named a?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;b&#39;</span> <span class="k">in</span> <span class="nx">o</span><span class="p">);</span> <span class="c1">// does o have a property named b?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_span_class_monospaced_in_span_operator_2"><span class="monospaced">in</span> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">a</span><span class="o">:</span> <span class="kc">false</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;a&#39;</span> <span class="k">in</span> <span class="nx">o</span><span class="p">);</span> <span class="c1">// true or false?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_span_class_monospaced_for_8230_in_span_loop"><span class="monospaced">for &#8230; in</span> loop</h2>
<div class="sectionbody">
<div class="paragraph"><p>Enumerates over <em>enumerable</em> properties of an object</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">a</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">b</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">c</span><span class="o">:</span> <span class="mi">3</span>
<span class="p">};</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">o</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s2">&quot;| &quot;</span> <span class="o">+</span> <span class="nx">prop</span> <span class="o">+</span> <span class="s1">&#39;:&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">+</span> <span class="s2">&quot; |&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_the_global_object">The global object</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
Every JavaScript environment has a single global object
</p>
</li>
<li>
<p>
All global variables are properties of this object
</p>
</li>
<li>
<p>
In web browsers, the global object is <span class="monospaced">window</span>
</p>
</li>
</ul></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g1</span> <span class="o">=</span> <span class="s2">&quot;Just an innocent global&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">g1</span> <span class="o">==</span> <span class="nx">g1</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">g2</span> <span class="o">=</span> <span class="s2">&quot;Another global&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">g2</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_accessing_a_shadowed_global">Accessing a "shadowed" global</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">// can we access the global g here?</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_accessing_a_shadowed_global_2">Accessing a "shadowed" global</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">g</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_accessing_shadowed_non_globals">Accessing "shadowed" non-globals?</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">g</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="c1">// can we access the &quot;middle&quot; g here?</span>
<span class="p">})();</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Sorry, no</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_array_literals">Array literals</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_mixed_type_arrays">Mixed type arrays</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">14</span><span class="p">,</span> <span class="s2">&quot;shoe&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">a</span><span class="o">:</span> <span class="mi">8</span><span class="p">}];</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mf">3.1415</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">a</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_some_useful_array_methods">Some useful array methods</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;coffee&quot;</span><span class="p">,</span> <span class="s2">&quot;tea&quot;</span><span class="p">,</span> <span class="s2">&quot;beer&quot;</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">join</span><span class="p">());</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot; or &quot;</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;?&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot; please&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">join</span><span class="p">());</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_nested_object_array_structures">Nested object / array structures</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">14</span><span class="p">,</span> <span class="s2">&quot;shoe&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">a</span><span class="o">:</span> <span class="mi">8</span><span class="p">}];</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="mf">3.1415</span><span class="p">);</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">b</span><span class="o">:</span> <span class="p">[</span><span class="mi">9</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="s2">&quot;r&quot;</span><span class="p">]]});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">a</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">4</span><span class="p">][</span><span class="s1">&#39;b&#39;</span><span class="p">][</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_javascript_does_not_have_real_arrays">JavaScript does not have real arrays</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">a</span><span class="p">);</span>
<span class="nx">a</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;huh?&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="k">delete</span> <span class="nx">a</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span> <span class="c1">// did array shift to fill in gap left at index 1?</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="s2">&quot;2&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">[</span><span class="nx">s</span><span class="p">]);</span> <span class="c1">// can we access array elements with a string index?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_functional_programming_with_arrays">Functional programming with arrays</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">forEach</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">fn</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="nx">fn</span><span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">printPlus1</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">((</span><span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="nx">forEach</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">printPlus1</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_objects_as_namespaces">Objects as namespaces</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">MyApp</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">Module1</span><span class="o">:</span> <span class="p">{</span>
<span class="c1">// public functions (methods) and variables (properties)</span>
<span class="p">},</span>
<span class="nx">Module2</span><span class="o">:</span> <span class="p">(</span><span class="kd">function</span><span class="p">(){</span> <span class="c1">// note enclosing parentheses - immediate function</span>
<span class="c1">// private code and variables</span>
<span class="k">return</span> <span class="p">{</span>
<span class="c1">// public properties/methods</span>
<span class="p">};</span>
<span class="p">})(),</span>
<span class="nx">Module3</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="c1">// just a function</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_returning_an_object">Function returning an object</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="nx">account</span><span class="p">,</span> <span class="nx">name</span><span class="p">){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">account</span><span class="o">:</span> <span class="nx">account</span><span class="p">,</span>
<span class="nx">name</span><span class="o">:</span> <span class="nx">name</span>
<span class="p">};</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_objects_with_methods_and_private_variables">Objects with methods and private variables</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCounter</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">reset</span><span class="p">(</span><span class="nx">newCount</span><span class="p">){</span>
<span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">current</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">count</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">reset</span><span class="o">:</span> <span class="nx">reset</span><span class="p">,</span>
<span class="nx">current</span><span class="o">:</span> <span class="nx">current</span><span class="p">,</span>
<span class="nx">increment</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_1">Exercise 1</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">map</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">fn</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">plus1</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">21</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mi">25</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">a2</span> <span class="o">=</span> <span class="nx">map</span><span class="p">(</span><span class="nx">a1</span><span class="p">,</span> <span class="nx">plus1</span><span class="p">);</span> <span class="c1">// [22, 33, 26]</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_2">Exercise 2</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">translateNote</span><span class="p">(</span><span class="nx">note</span><span class="p">){</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">note</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="s1">&#39;c&#39;</span><span class="o">:</span>
<span class="k">return</span> <span class="s1">&#39;dough&#39;</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="s1">&#39;d&#39;</span><span class="o">:</span>
<span class="k">return</span> <span class="s1">&#39;ray&#39;</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">default</span><span class="o">:</span>
<span class="k">return</span> <span class="s1">&#39;I only know 2 notes&#39;</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">translateNote</span><span class="p">(</span><span class="s1">&#39;c&#39;</span><span class="p">));</span> <span class="c1">// &#39;dough&#39;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">translateNote</span><span class="p">(</span><span class="s1">&#39;d&#39;</span><span class="p">));</span> <span class="c1">// &#39;ray&#39;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">translateNote</span><span class="p">(</span><span class="s1">&#39;e&#39;</span><span class="p">));</span> <span class="c1">// &#39;I only know 2 notes&#39;</span>
<span class="c1">// rewrite translateNote to use only 1 return statement</span>
<span class="c1">// hint: don&#39;t use switch</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_3">Exercise 3</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">account</span><span class="p">){</span>
<span class="cm">/****</span>
<span class="cm"> your code here</span>
<span class="cm"> customer object has...</span>
<span class="cm"> - a name property containing the customer&#39;s name</span>
<span class="cm"> - an account property containing the customer&#39;s account number</span>
<span class="cm"> - an addOrder method that takes 1 argument: order number</span>
<span class="cm"> - a getOrders method that returns a string containing info about</span>
<span class="cm"> customer&#39;s orders, per below example</span>
<span class="cm"> - info about orders can only be accessed via the getOrders method</span>
<span class="cm"> */</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bob</span> <span class="o">=</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="s1">&#39;Bob&#39;</span><span class="p">,</span> <span class="mi">5673</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">getOrders</span><span class="p">());</span> <span class="c1">// &quot;Bob has no orders&quot;</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90023</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">getOrders</span><span class="p">());</span> <span class="c1">// &quot;Bob&#39;s order: 90023&quot;</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90028</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">getOrders</span><span class="p">());</span> <span class="c1">// &quot;Bob&#39;s orders: 90023, 90028&quot;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_4">Exercise 4</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">reduce</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">fn</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">add</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">+</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">mult</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">*</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">add</span><span class="p">));</span> <span class="c1">// 12</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">reduce</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">mult</span><span class="p">));</span> <span class="c1">// 42</span>
</pre></div></div></div>
</div>
</div>
</div>
<div id="footnotes"><hr></div>
<div id="footer">
<div id="footer-text">
Last updated 2012-08-02 14:48:26 Eastern Daylight Time
</div>
</div>
</body>
</html>

JavaScript III - Constructor Functions and the this Keyword

Content and target audience

JavaScript III - Constructor Functions and the this Keyword

Digging into object oriented programing in JavaScript.

Prototypes and object inheritance will be covered in later talks.

You are familiar with basics of functional programming and working with objects in JavaScript (covered in JavaScript I - Variables, Functions, and Scope and JavaScript II - Objects, Arrays, and Booleans)

Resources and tools

Not as I do…​

Avoid document.writeln() - not useful in real life, but useful for examples

The this keyword

What does it mean?

this in global scope

document.writeln(x);

this.x = 1;
document.writeln(x);

window.x = 2;
document.writeln(this.x);

document.writeln(this === window);

this in functions

document.writeln(x);
this.x = 1;
document.writeln(x);

function f(){
    document.writeln(this.x);
    this.x = 2;
    document.writeln(this.x);
}
f();
document.writeln(this.x);

window.x = 3;
document.writeln(this.x);

this in functions

this.x = 1;

function f(){
    document.writeln(this.x);
    this.x = 3;
}
var o = {
    x: 2,
    m: f
};
document.writeln(this.x);
document.writeln(o.x);
f();
document.writeln(this.x);
document.writeln(o.x);

this in function invoked as method

this.x = 1;

function f(){
    document.writeln(this.x);
    this.x = 3;
}
var o = {
    x: 2,
    m: f
};
document.writeln(this.x);
document.writeln(o.x);
o.m();
document.writeln(this.x);
document.writeln(o.x);

this in function invoked as method

var y = 1;
var o = {
    x: 2,
    m: function(){
        this.y = 3;
    }
};
document.writeln(o.x + '|' + o.y);
o.m();
document.writeln(o.x + '|' + o.y);
document.writeln(this.y);

this in function invoked as method

var x = 1;
var f = function(){
    this.x += 10;
};
var o = {
    x: 2,
    o: { x: 3 }
};
o.m = f;
o.o.m = f;

document.writeln(x + '|' + o.x + '|' + o.o.x);
f();
document.writeln(x + '|' + o.x + '|' + o.o.x);
o.m();
document.writeln(x + '|' + o.x + '|' + o.o.x);
o.o.m();
document.writeln(x + '|' + o.x + '|' + o.o.x);

Function invocation patterns seen thus far…​

  • function: f();

  • method: o.f();

Constructor functions and the new operator

function C(){
    this.x = 2;
}
var a = new C;
document.writeln(a.x);

Constructor functions and the new operator

function C(){
    // var this = {};
    this.x = 2;
    // return this;
}
var a = new C;
document.writeln(a.x);

Constructor functions and the new operator

function C(){
    this.x = 2;
}
var a = new C();
document.writeln(a.x);

Constructor functions and the new operator

function C(){
    this.x = 2;
}
var a = C();
document.writeln(a.x);

Constructor functions and the new operator

var x = 1;
function C(){
    this.x = 2;
}
var a = C();
document.writeln(x);
document.writeln(a);

Function invocation patterns seen thus far…​

  • function: f();

  • method: o.f();

  • constructor: x = new F; or x = new F();

Function invocation patterns seen thus far…​

var x = 1;
function C(){
    this.x = 2;
}
var o = {
    x: 3,
    m: C
};
var a = new C;
document.writeln(x + '|' + o.x + '|' + a.x);
o.m();
document.writeln(x + '|' + o.x + '|' + a.x);
C();
document.writeln(x + '|' + o.x + '|' + a.x);

Functions are objects

function f(){
    document.writeln(f.y);
    if (typeof f.z === 'function') f.z();
    document.writeln('<hr>');
}
f();
f.y = 1;
f();
f.z = function(){
    document.writeln(2);
}
f();

apply function invocation pattern

function f(){
    this.x = 1;
}
var o = { x: 2 };
f.apply(o);
document.writeln(o.x);

apply function invocation pattern

var o1 = {
    x: 1,
    m: function f(){
        this.x = 2;
    }
};
var o2 = { x: 3 };
o1.m.apply(o2);
document.writeln(o1.x);
document.writeln(o2.x);

Passing arguments with apply

function f(_x, _y){
    this.x = _x;
    this.y = _y;
}
var o = {
    x: 1,
    y: 2
};
document.writeln(o.x + '|' + o.y);
f.apply(o, [3, 4]);
document.writeln(o.x + '|' + o.y);

call is similar to apply

function f(_x, _y){
    this.x = _x;
    this.y = _y;
}
var o = {
    x: 1,
    y: 2
};
document.writeln(o.x + '|' + o.y);
f.call(o, 3, 4);
document.writeln(o.x + '|' + o.y);

Contexts affecting meaning of this (comprehensive list)

In global scope

global object

In functions - depends on invocation pattern

function

global object

method

object the function is a method of

constructor

new object returned by constructor

apply or call

the specified object

Objects with methods and private variables

function makeCounter(){
    var count = 0;
    function reset(newCount){
        count = newCount || 0;
    }
    function current(){
        return count;
    }
    return {
        reset: reset,
        current: current,
        increment: function (amount) {
            if (typeof amount === 'undefined') amount = 1;
            count += amount;
        }
    };
}

Objects with methods operating on public properties

function Counter(){
    this.count = 0;
    this.reset = function (newCount) {
        this.count = newCount || 0;
    };
    this.increment = function (amount) {
        if (typeof amount === 'undefined') amount = 1;
        this.count += amount;
    }
}

var c = new Counter;
document.writeln(c.count);

c.increment(2);
document.writeln(c.count);

c.reset();
document.writeln(c.count);

Method chaining

function Counter(){
    this.count = 0;
    this.reset = function (newCount) {
        this.count = newCount || 0;
        return this;
    };
    this.increment = function (amount) {
        if (typeof amount === 'undefined') amount = 1;
        this.count += amount;
        return this;
    }
}
var c = new Counter;
document.writeln(c.count);
document.writeln(c.increment().count);
document.writeln(c.reset().count);
document.writeln(c.reset(5).increment(10).count);
document.writeln(c.count);

Exercise 1

function Customer(name, account){
    /****
      your code here

      Customer is a constructor function

      customer object has...
       - a public name property containing the customer's name
       - a public account property containing the customer's account number
       - a public orders property containing the customer's orders (as an array)
       - info about orders directly accessible via the orders property
       - an addOrder method that takes 1 argument: order number
     */
}

var bob = new Customer('Bob', 5673);
document.writeln(bob.account); // 5673
bob.addOrder(90023);
document.writeln(bob.orders); // [90023]
bob.addOrder(90028);
document.writeln(bob.orders); // [90023, 90028]

Exercise 2

function HTMLformatter(content){
    // your code here
    // HTMLformatter is a constructor function
}
var s = new HTMLformatter("hi");
document.writeln(s.text);               // hi
s.text = "hello";
document.writeln(s.bold());             // <strong>hello</strong>
document.writeln(s.italic());           // <em>hello</em>
document.writeln(s.bold().italic());    // <em><strong>hello</strong></em>

Exercise 3

Rudimentary inheritance - objects that share methods

function HTMLformatter(content){
    // your code here (leave intact from exercise 2)
}
// feel free to add code in between / before / after
function HTMLformatter2(content){
    // your code here
    // HTMLformatter2 does everything HTMLformatter does, but adds the box method
    // Avoid repeating code for methods already defined in HTMLformatter
}

var s = new HTMLformatter2("hi");
document.writeln(s.text);               // hi
s.text = "hello";
document.writeln(s.box());              // <div style="border: 1px solid black;">hello</div>
document.writeln(s.italic().box());     // <div style="border: 1px solid black;"><em>hello</em></div>

Exercise 4

function makeCustomer(name, account){
    /****
      your code here

      makeCustomer is NOT a constructor function (we do not use the new operator)
      but accomplishes the same as the constructor function in Exercise 1
      hint: think about the approach used to create objects in Session II

      customer object has...
       - a public name property containing the customer's name
       - a public account property containing the customer's account number
       - a public orders property containing the customer's orders (as an array)
       - info about orders directly accessible via the orders property
       - an addOrder method that takes 1 argument: order number
     */
}

var bob = makeCustomer('Bob', 5673);
document.writeln(bob.account); // 5673
bob.addOrder(90023);
document.writeln(bob.orders); // [90023]
bob.addOrder(90028);
document.writeln(bob.orders); // [90023, 90028]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.6.7" />
<title>JavaScript III - Constructor Functions and the <tt>this</tt> Keyword</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
pre {
padding: 0;
margin: 0;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
tt {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
.monospaced {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/*
pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = { // Namespace.
/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////
/* Author: Mihai Bazon, September 2002
* http://students.infoiasi.ro/~mishoo
*
* Table Of Content generator
* Version: 0.4
*
* Feel free to use this script under the terms of the GNU General Public
* License, as long as you do not remove or alter this notice.
*/
/* modified by Troy D. Hanson, September 2006. License: GPL */
/* modified by Stuart Rackham, 2006, 2009. License: GPL */
// toclevels = 1..4.
toc: function (toclevels) {
function getText(el) {
var text = "";
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
text += i.data;
else if (i.firstChild != null)
text += getText(i);
}
return text;
}
function TocEntry(el, text, toclevel) {
this.element = el;
this.text = text;
this.toclevel = toclevel;
}
function tocEntries(el, toclevels) {
var result = new Array;
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
// Function that scans the DOM tree for header elements (the DOM2
// nodeIterator API would be a better technique but not supported by all
// browsers).
var iterate = function (el) {
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
var mo = re.exec(i.tagName);
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
}
iterate(i);
}
}
}
iterate(el);
return result;
}
var toc = document.getElementById("toc");
if (!toc) {
return;
}
// Delete existing TOC entries in case we're reloading the TOC.
var tocEntriesToRemove = [];
var i;
for (i = 0; i < toc.childNodes.length; i++) {
var entry = toc.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div'
&& entry.getAttribute("class")
&& entry.getAttribute("class").match(/^toclevel/))
tocEntriesToRemove.push(entry);
}
for (i = 0; i < tocEntriesToRemove.length; i++) {
toc.removeChild(tocEntriesToRemove[i]);
}
// Rebuild TOC entries.
var entries = tocEntries(document.getElementById("content"), toclevels);
for (var i = 0; i < entries.length; ++i) {
var entry = entries[i];
if (entry.element.id == "")
entry.element.id = "_toc_" + i;
var a = document.createElement("a");
a.href = "#" + entry.element.id;
a.appendChild(document.createTextNode(entry.text));
var div = document.createElement("div");
div.appendChild(a);
div.className = "toclevel" + entry.toclevel;
toc.appendChild(div);
}
if (entries.length == 0)
toc.parentNode.removeChild(toc);
},
/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////
/* Based on footnote generation code from:
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
*/
footnotes: function () {
// Delete existing footnote entries in case we're reloading the footnodes.
var i;
var noteholder = document.getElementById("footnotes");
if (!noteholder) {
return;
}
var entriesToRemove = [];
for (i = 0; i < noteholder.childNodes.length; i++) {
var entry = noteholder.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
entriesToRemove.push(entry);
}
for (i = 0; i < entriesToRemove.length; i++) {
noteholder.removeChild(entriesToRemove[i]);
}
// Rebuild footnote entries.
var cont = document.getElementById("content");
var spans = cont.getElementsByTagName("span");
var refs = {};
var n = 0;
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnote") {
n++;
var note = spans[i].getAttribute("data-note");
if (!note) {
// Use [\s\S] in place of . so multi-line matches work.
// Because JavaScript has no s (dotall) regex flag.
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
spans[i].innerHTML =
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
spans[i].setAttribute("data-note", note);
}
noteholder.innerHTML +=
"<div class='footnote' id='_footnote_" + n + "'>" +
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
n + "</a>. " + note + "</div>";
var id =spans[i].getAttribute("id");
if (id != null) refs["#"+id] = n;
}
}
if (n == 0)
noteholder.parentNode.removeChild(noteholder);
else {
// Process footnoterefs.
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnoteref") {
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
href = href.match(/#.*/)[0]; // Because IE return full URL.
n = refs[href];
spans[i].innerHTML =
"[<a href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
}
}
}
},
install: function(toclevels) {
var timerId;
function reinstall() {
asciidoc.footnotes();
if (toclevels) {
asciidoc.toc(toclevels);
}
}
function reinstallAndRemoveTimer() {
clearInterval(timerId);
reinstall();
}
timerId = setInterval(reinstall, 500);
if (document.addEventListener)
document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
else
window.onload = reinstallAndRemoveTimer;
}
}
asciidoc.install();
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>JavaScript III - Constructor Functions and the <tt>this</tt> Keyword</h1>
<span id="author">Bruce Harris, 8/7/12</span><br />
</div>
<div id="content">
<div class="sect1">
<h2 id="_content_and_target_audience">Content and target audience</h2>
<div class="sectionbody">
<div class="paragraph"><p><strong>JavaScript III - Constructor Functions and the <tt>this</tt> Keyword</strong></p></div>
<div class="paragraph"><p>Digging into object oriented programing in JavaScript.</p></div>
<div class="paragraph"><p>Prototypes and object inheritance will be covered in later talks.</p></div>
<div class="paragraph"><p>You are familiar with basics of functional programming and working with
objects in JavaScript
(covered in
<a href="http://bruceharris.net/techtalks">JavaScript I - Variables, Functions, and Scope</a> and
<a href="http://bruceharris.net/techtalks">JavaScript II - Objects, Arrays, and Booleans</a>)</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_resources_and_tools">Resources and tools</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
These slides: <a href="http://bruceharris.net/techtalks/">http://bruceharris.net/techtalks</a>
</p>
</li>
<li>
<p>
Sandboxes: <a href="http://codepen.io/pen">CodePen</a>, <a href="http://jsfiddle.net/">JSFiddle</a>, <a href="http://jsbin.com/">JS Bin</a>
</p>
</li>
<li>
<p>
Use your browser&#8217;s debugger / developer tools
</p>
</li>
<li>
<p>
Reference: <a href="https://developer.mozilla.org/en/JavaScript/">Mozilla Developer Network</a>
</p>
</li>
<li>
<p>
Instruction (online book): <a href="http://eloquentjavascript.net/contents.html">Eloquent JavaScript</a>
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_not_as_i_do_8230">Not as I do&#8230;</h2>
<div class="sectionbody">
<div class="paragraph"><p>Avoid <tt>document.writeln()</tt> - not useful in real life, but useful for examples</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_the_tt_this_tt_keyword">The <tt>this</tt> keyword</h2>
<div class="sectionbody">
<div class="paragraph"><p><strong>What does it mean?</strong></p></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_this_tt_in_global_scope"><tt>this</tt> in global scope</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span> <span class="o">===</span> <span class="nb">window</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_this_tt_in_functions"><tt>this</tt> in functions</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_this_tt_in_functions_2"><tt>this</tt> in functions</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="nx">f</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_this_tt_in_function_invoked_as_em_method_em"><tt>this</tt> in function invoked as <em>method</em></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="nx">f</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_this_tt_in_function_invoked_as_em_method_em_2"><tt>this</tt> in function invoked as <em>method</em></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_this_tt_in_function_invoked_as_em_method_em_3"><tt>this</tt> in function invoked as <em>method</em></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">+=</span> <span class="mi">10</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">o</span><span class="o">:</span> <span class="p">{</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">3</span> <span class="p">}</span>
<span class="p">};</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span> <span class="o">=</span> <span class="nx">f</span><span class="p">;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">m</span> <span class="o">=</span> <span class="nx">f</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_invocation_patterns_seen_thus_far_8230">Function invocation patterns seen thus far&#8230;</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
function: <tt>f();</tt>
</p>
</li>
<li>
<p>
method: <tt>o.f();</tt>
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_constructor_functions_and_the_tt_new_tt_operator">Constructor functions and the <tt>new</tt> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_constructor_functions_and_the_tt_new_tt_operator_2">Constructor functions and the <tt>new</tt> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="c1">// var this = {};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">// return this;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_constructor_functions_and_the_tt_new_tt_operator_3">Constructor functions and the <tt>new</tt> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_constructor_functions_and_the_tt_new_tt_operator_4">Constructor functions and the <tt>new</tt> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_constructor_functions_and_the_tt_new_tt_operator_5">Constructor functions and the <tt>new</tt> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_invocation_patterns_seen_thus_far_8230_2">Function invocation patterns seen thus far&#8230;</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
function: <tt>f();</tt>
</p>
</li>
<li>
<p>
method: <tt>o.f();</tt>
</p>
</li>
<li>
<p>
constructor: <tt>x = new F;</tt> or <tt>x = new F();</tt>
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_invocation_patterns_seen_thus_far_8230_3">Function invocation patterns seen thus far&#8230;</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="nx">C</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_functions_are_objects">Functions are objects</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">f</span><span class="p">.</span><span class="nx">z</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span><span class="p">)</span> <span class="nx">f</span><span class="p">.</span><span class="nx">z</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;&lt;hr&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">z</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_apply_tt_function_invocation_pattern"><tt>apply</tt> function invocation pattern</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">2</span> <span class="p">};</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">o</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_apply_tt_function_invocation_pattern_2"><tt>apply</tt> function invocation pattern</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o1</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">o2</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">3</span> <span class="p">};</span>
<span class="nx">o1</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">o2</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o1</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o2</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_passing_arguments_with_tt_apply_tt">Passing arguments with <tt>apply</tt></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">_x</span><span class="p">,</span> <span class="nx">_y</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="nx">_x</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="nx">_y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">y</span><span class="o">:</span> <span class="mi">2</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_tt_call_tt_is_similar_to_tt_apply_tt"><tt>call</tt> is similar to <tt>apply</tt></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">_x</span><span class="p">,</span> <span class="nx">_y</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="nx">_x</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="nx">_y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">y</span><span class="o">:</span> <span class="mi">2</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_contexts_affecting_meaning_of_tt_this_tt_comprehensive_list">Contexts affecting meaning of <tt>this</tt> (comprehensive list)</h2>
<div class="sectionbody">
<div class="hdlist"><table>
<tr>
<td class="hdlist1">
In global scope
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
global object
</p>
</td>
</tr>
</table></div>
<div class="paragraph"><p><strong>In functions - depends on invocation pattern</strong></p></div>
<div class="hdlist"><table>
<tr>
<td class="hdlist1">
function
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
global object
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
method
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
object the function is a method of
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
constructor
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
new object returned by constructor
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
<tt>apply</tt> or <tt>call</tt>
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
the specified object
</p>
</td>
</tr>
</table></div>
</div>
</div>
<div class="sect1">
<h2 id="_objects_with_methods_and_private_variables">Objects with methods and private variables</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCounter</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">reset</span><span class="p">(</span><span class="nx">newCount</span><span class="p">){</span>
<span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">current</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">count</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">reset</span><span class="o">:</span> <span class="nx">reset</span><span class="p">,</span>
<span class="nx">current</span><span class="o">:</span> <span class="nx">current</span><span class="p">,</span>
<span class="nx">increment</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_objects_with_methods_operating_on_public_properties">Objects with methods operating on public properties</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">Counter</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">newCount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">increment</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Counter</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
<span class="nx">c</span><span class="p">.</span><span class="nx">increment</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
<span class="nx">c</span><span class="p">.</span><span class="nx">reset</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_method_chaining">Method chaining</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">Counter</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">newCount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">increment</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Counter</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">increment</span><span class="p">().</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">reset</span><span class="p">().</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">reset</span><span class="p">(</span><span class="mi">5</span><span class="p">).</span><span class="nx">increment</span><span class="p">(</span><span class="mi">10</span><span class="p">).</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_1">Exercise 1</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">Customer</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">account</span><span class="p">){</span>
<span class="cm">/****</span>
<span class="cm"> your code here</span>
<span class="cm"> Customer is a constructor function</span>
<span class="cm"> customer object has...</span>
<span class="cm"> - a public name property containing the customer&#39;s name</span>
<span class="cm"> - a public account property containing the customer&#39;s account number</span>
<span class="cm"> - a public orders property containing the customer&#39;s orders (as an array)</span>
<span class="cm"> - info about orders directly accessible via the orders property</span>
<span class="cm"> - an addOrder method that takes 1 argument: order number</span>
<span class="cm"> */</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bob</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Customer</span><span class="p">(</span><span class="s1">&#39;Bob&#39;</span><span class="p">,</span> <span class="mi">5673</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span> <span class="c1">// 5673</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90023</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023]</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90028</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023, 90028]</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_2">Exercise 2</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">HTMLformatter</span><span class="p">(</span><span class="nx">content</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="c1">// HTMLformatter is a constructor function</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HTMLformatter</span><span class="p">(</span><span class="s2">&quot;hi&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">text</span><span class="p">);</span> <span class="c1">// hi</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">text</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">bold</span><span class="p">());</span> <span class="c1">// &lt;strong&gt;hello&lt;/strong&gt;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">italic</span><span class="p">());</span> <span class="c1">// &lt;em&gt;hello&lt;/em&gt;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">bold</span><span class="p">().</span><span class="nx">italic</span><span class="p">());</span> <span class="c1">// &lt;em&gt;&lt;strong&gt;hello&lt;/strong&gt;&lt;/em&gt;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_3">Exercise 3</h2>
<div class="sectionbody">
<div class="paragraph"><p>Rudimentary inheritance - objects that share methods</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">HTMLformatter</span><span class="p">(</span><span class="nx">content</span><span class="p">){</span>
<span class="c1">// your code here (leave intact from exercise 2)</span>
<span class="p">}</span>
<span class="c1">// feel free to add code in between / before / after</span>
<span class="kd">function</span> <span class="nx">HTMLformatter2</span><span class="p">(</span><span class="nx">content</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="c1">// HTMLformatter2 does everything HTMLformatter does, but adds the box method</span>
<span class="c1">// Avoid repeating code for methods already defined in HTMLformatter</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HTMLformatter2</span><span class="p">(</span><span class="s2">&quot;hi&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">text</span><span class="p">);</span> <span class="c1">// hi</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">text</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">box</span><span class="p">());</span> <span class="c1">// &lt;div style=&quot;border: 1px solid black;&quot;&gt;hello&lt;/div&gt;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">italic</span><span class="p">().</span><span class="nx">box</span><span class="p">());</span> <span class="c1">// &lt;div style=&quot;border: 1px solid black;&quot;&gt;&lt;em&gt;hello&lt;/em&gt;&lt;/div&gt;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_4">Exercise 4</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">account</span><span class="p">){</span>
<span class="cm">/****</span>
<span class="cm"> your code here</span>
<span class="cm"> makeCustomer is NOT a constructor function (we do not use the new operator)</span>
<span class="cm"> but accomplishes the same as the constructor function in Exercise 1</span>
<span class="cm"> hint: think about the approach used to create objects in Session II</span>
<span class="cm"> customer object has...</span>
<span class="cm"> - a public name property containing the customer&#39;s name</span>
<span class="cm"> - a public account property containing the customer&#39;s account number</span>
<span class="cm"> - a public orders property containing the customer&#39;s orders (as an array)</span>
<span class="cm"> - info about orders directly accessible via the orders property</span>
<span class="cm"> - an addOrder method that takes 1 argument: order number</span>
<span class="cm"> */</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bob</span> <span class="o">=</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="s1">&#39;Bob&#39;</span><span class="p">,</span> <span class="mi">5673</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span> <span class="c1">// 5673</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90023</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023]</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90028</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023, 90028]</span>
</pre></div></div></div>
</div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Last updated 2012-08-07 15:20:23 Eastern Daylight Time
</div>
</div>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>JavaScript III - Constructor Functions and the <tt>this</tt> Keyword</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="copyright" content="Copyright &#169; Bruce Harris, 8/7/12" />
<meta name="generator" content="AsciiDoc 8.6.7" />
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
pre {
padding: 0;
margin: 0;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
tt {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
.monospaced {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/* slidy.css
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
/*
SJR: 2010-09-29: Modified for AsciiDoc slidy backend.
Mostly just commented out stuff that is handled by AsciiDoc's CSS files.
*/
body
{
margin: 0 0 0 0;
padding: 0 0 0 0;
width: 100%;
height: 100%;
color: black;
background-color: white;
/*
font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
*/
font-size: 14pt;
}
div.toolbar {
position: fixed; z-index: 200;
top: auto; bottom: 0; left: 0; right: 0;
height: 1.2em; text-align: right;
padding-left: 1em;
padding-right: 1em;
font-size: 60%;
color: red;
background-color: rgb(240,240,240);
border-top: solid 1px rgb(180,180,180);
}
div.toolbar span.copyright {
color: black;
margin-left: 0.5em;
}
div.initial_prompt {
position: absolute;
z-index: 1000;
bottom: 1.2em;
width: 90%;
background-color: rgb(200,200,200);
opacity: 0.35;
background-color: rgb(200,200,200, 0.35);
cursor: pointer;
}
div.initial_prompt p.help {
text-align: center;
}
div.initial_prompt p.close {
text-align: right;
font-style: italic;
}
div.slidy_toc {
position: absolute;
z-index: 300;
width: 60%;
max-width: 30em;
height: 30em;
overflow: auto;
top: auto;
right: auto;
left: 4em;
bottom: 4em;
padding: 1em;
background: rgb(240,240,240);
border-style: solid;
border-width: 2px;
font-size: 60%;
}
div.slidy_toc .toc_heading {
text-align: center;
width: 100%;
margin: 0;
margin-bottom: 1em;
border-bottom-style: solid;
border-bottom-color: rgb(180,180,180);
border-bottom-width: 1px;
}
div.slide {
z-index: 20;
margin: 0 0 0 0;
padding-top: 0;
padding-bottom: 0;
padding-left: 20px;
padding-right: 20px;
border-width: 0;
clear: both;
top: 0;
bottom: 0;
left: 0;
right: 0;
line-height: 120%;
background-color: transparent;
}
div.background {
display: none;
}
div.handout {
margin-left: 20px;
margin-right: 20px;
}
div.slide.titlepage {
text-align: center;
}
div.slide.titlepage.h1 {
padding-top: 10%;
}
div.slide h1 {
padding-left: 0;
padding-right: 20pt;
padding-top: 4pt;
padding-bottom: 4pt;
margin-top: 0;
margin-left: 0;
margin-right: 60pt;
margin-bottom: 0.5em;
display: block;
font-size: 160%;
line-height: 1.2em;
background: transparent;
}
div.toc {
position: absolute;
top: auto;
bottom: 4em;
left: 4em;
right: auto;
width: 60%;
max-width: 30em;
height: 30em;
border: solid thin black;
padding: 1em;
background: rgb(240,240,240);
color: black;
z-index: 300;
overflow: auto;
display: block;
visibility: visible;
}
div.toc-heading {
width: 100%;
border-bottom: solid 1px rgb(180,180,180);
margin-bottom: 1em;
text-align: center;
}
/*
pre {
font-size: 80%;
font-weight: bold;
line-height: 120%;
padding-top: 0.2em;
padding-bottom: 0.2em;
padding-left: 1em;
padding-right: 1em;
border-style: solid;
border-left-width: 1em;
border-top-width: thin;
border-right-width: thin;
border-bottom-width: thin;
border-color: #95ABD0;
color: #00428C;
background-color: #E4E5E7;
}
*/
/*
li pre { margin-left: 0; }
blockquote { font-style: italic }
img { background-color: transparent }
p.copyright { font-size: smaller }
*/
.center { text-align: center }
.footnote { font-size: smaller; margin-left: 2em; }
/*
a img { border-width: 0; border-style: none }
*/
a:visited { color: navy }
a:link { color: navy }
a:hover { color: red; text-decoration: underline }
a:active { color: red; text-decoration: underline }
a {text-decoration: none}
.navbar a:link {color: white}
.navbar a:visited {color: yellow}
.navbar a:active {color: red}
.navbar a:hover {color: red}
/*
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
li { margin-left: 0.5em; margin-top: 0.5em; }
li li { font-size: 85%; font-style: italic }
li li li { font-size: 85%; font-style: normal }
*/
div dt
{
margin-left: 0;
margin-top: 1em;
margin-bottom: 0.5em;
font-weight: bold;
}
div dd
{
margin-left: 2em;
margin-bottom: 0.5em;
}
/*
p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
margin-left: 1em;
margin-right: 1em;
}
*/
p.subhead { font-weight: bold; margin-top: 2em; }
.smaller { font-size: smaller }
.bigger { font-size: 130% }
/*
td,th { padding: 0.2em }
*/
ul {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ol {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
/*
ul li {
list-style: square;
margin: 0.1em 0em 0.6em 0;
padding: 0 0 0 0;
line-height: 140%;
}
ol li {
margin: 0.1em 0em 0.6em 1.5em;
padding: 0 0 0 0px;
line-height: 140%;
list-style-type: decimal;
}
li ul li {
font-size: 85%;
font-style: italic;
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li li ul li {
font-size: 85%;
font-style: normal;
list-style-type: circle;
background: transparent;
padding: 0 0 0 0;
}
li li li ul li {
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li ol li {
list-style-type: decimal;
}
li li ol li {
list-style-type: decimal;
}
*/
/*
setting class="outline" on ol or ul makes it behave as an
ouline list where blocklevel content in li elements is
hidden by default and can be expanded or collapsed with
mouse click. Set class="expand" on li to override default
*/
ol.outline li:hover { cursor: pointer }
ol.outline li.nofold:hover { cursor: default }
ul.outline li:hover { cursor: pointer }
ul.outline li.nofold:hover { cursor: default }
ol.outline { list-style:decimal; }
ol.outline ol { list-style-type:lower-alpha }
ol.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
ul.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
/* for slides with class "title" in table of contents */
a.titleslide { font-weight: bold; font-style: italic }
/*
hide images for work around for save as bug
where browsers fail to save images used by CSS
*/
img.hidden { display: none; visibility: hidden }
div.initial_prompt { display: none; visibility: hidden }
div.slide {
visibility: visible;
position: inherit;
}
div.handout {
border-top-style: solid;
border-top-width: thin;
border-top-color: black;
}
@media screen {
.hidden { display: none; visibility: visible }
div.slide.hidden { display: block; visibility: visible }
div.handout.hidden { display: block; visibility: visible }
div.background { display: none; visibility: hidden }
body.single_slide div.initial_prompt { display: block; visibility: visible }
body.single_slide div.background { display: block; visibility: visible }
body.single_slide div.background.hidden { display: none; visibility: hidden }
body.single_slide .invisible { visibility: hidden }
body.single_slide .hidden { display: none; visibility: hidden }
body.single_slide div.slide { position: absolute }
body.single_slide div.handout { display: none; visibility: hidden }
}
@media print {
.hidden { display: block; visibility: visible }
/*
div.slide pre { font-size: 60%; padding-left: 0.5em; }
*/
div.toolbar { display: none; visibility: hidden; }
div.slidy_toc { display: none; visibility: hidden; }
div.background { display: none; visibility: hidden; }
div.slide { page-break-before: always }
/* :first-child isn't reliable for print media */
div.slide.first-slide { page-break-before: avoid }
}
/* SJR: AsciiDoc slidy backend tweaks */
ol, ul {
margin: 0.8em 1.5em 0.8em 1.8em;
}
li > ul, li > ol {
margin-top: 0.5em;
}
.outline > li.folded,
.outline > li.unfolded {
color: #527bbd;
}
ul > li{ color: #aaa; }
ul > li > *, ol > li > * { color: black; }
li {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
/*
pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
<script type="text/javascript">
/*<![CDATA[*/
/* slidy.js
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
// the slidy object implementation
var w3c_slidy = {
// classify which kind of browser we're running under
ns_pos: (typeof window.pageYOffset!='undefined'),
khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false),
opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false),
ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false),
iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false),
ie: (typeof document.all != "undefined" && !this.opera),
ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1),
ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1),
ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1),
ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1),
keyboardless: (this.ipad || this.iphone),
// are we running as XHTML? (doesn't work on Opera)
is_xhtml: /xml/.test(document.contentType),
slide_number: 0, // integer slide count: 0, 1, 2, ...
slide_number_element: null, // element containing slide number
slides: [], // set to array of slide div's
notes: [], // set to array of handout div's
backgrounds: [], // set to array of background div's
toolbar: null, // element containing toolbar
title: null, // document title
last_shown: null, // last incrementally shown item
eos: null, // span element for end of slide indicator
toc: null, // table of contents
outline: null, // outline element with the focus
selected_text_len: 0, // length of drag selection on document
view_all: 0, // 1 to view all slides + handouts
want_toolbar: true, // user preference to show/hide toolbar
mouse_click_enabled: true, // enables left click for next slide
scroll_hack: 0, // IE work around for position: fixed
disable_slide_click: false, // used by clicked anchors
lang: "en", // updated to language specified by html file
help_anchor: null, // used for keyboard focus hack in showToolbar()
help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html",
help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " +
"or Pg Up and Pg Dn. Use S and B to change font size.",
size_index: 0,
size_adjustment: 0,
sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
"22pt", "24pt", "26pt", "28pt", "30pt", "32pt"),
// needed for efficient resizing
last_width: 0,
last_height: 0,
// Needed for cross browser support for relative width/height on
// object elements. The work around is to save width/height attributes
// and then to recompute absolute width/height dimensions on resizing
objects: [],
// attach initialiation event handlers
set_up: function () {
var init = function() { w3c_slidy.init(); };
if (typeof window.addEventListener != "undefined")
window.addEventListener("load", init, false);
else
window.attachEvent("onload", init);
},
hide_slides: function () {
if (document.body && !w3c_slidy.initialized)
document.body.style.visibility = "hidden";
else
setTimeout(w3c_slidy.hide_slides, 50);
},
// hack to persuade IE to compute correct document height
// as needed for simulating fixed positioning of toolbar
ie_hack: function () {
window.resizeBy(0,-1);
window.resizeBy(0, 1);
},
init: function () {
//alert("slidy starting test 10");
document.body.style.visibility = "visible";
w3c_slidy_i18n.init();
this.add_toolbar();
this.wrap_implicit_slides();
this.collect_slides();
this.collect_notes();
this.collect_backgrounds();
this.objects = document.body.getElementsByTagName("object");
this.patch_anchors();
this.slide_number = this.find_slide_number(location.href);
window.offscreenbuffering = true;
this.size_adjustment = this.find_size_adjust();
this.time_left = this.find_duration();
this.hide_image_toolbar(); // suppress IE image toolbar popup
this.init_outliner(); // activate fold/unfold support
this.title = document.title;
// work around for opera bug
this.is_xhtml = (document.body.tagName == "BODY" ? false : true);
if (this.slides.length > 0)
{
var slide = this.slides[this.slide_number];
if (this.slide_number > 0)
{
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
this.set_eos_status(true);
}
else
{
this.last_shown = null;
this.set_visibility_all_incremental("hidden");
this.set_eos_status(!this.next_incremental_item(this.last_shown));
}
this.set_location();
this.add_class(this.slides[0], "first-slide");
w3c_slidy.show_slide(slide);
}
this.toc = this.table_of_contents();
this.add_initial_prompt();
// bind event handlers without interfering with custom page scripts
// Tap events behave too weirdly to support clicks reliably on
// iPhone and iPad, so exclude these from click handler
if (!this.keyboardless)
this.add_listener(document.body, "click", this.mouse_button_click);
this.add_listener(document, "keydown", this.key_down);
this.add_listener(document, "keypress", this.key_press);
this.add_listener(window, "resize", this.resized);
this.add_listener(window, "scroll", this.scrolled);
this.add_listener(window, "unload", this.unloaded);
if (!document.body.onclick)
document.body.onclick = function () { };
this.single_slide_view();
//this.set_location();
this.resized();
if (this.ie7)
setTimeout(w3c_slidy.ie_hack, 100);
this.show_toolbar();
// for back button detection
setInterval(function () { w3c_slidy.check_location(); }, 200);
w3c_slidy.initialized = true;
},
// create div element with links to each slide
table_of_contents: function () {
var toc = this.create_element("div");
this.add_class(toc, "slidy_toc hidden");
//toc.setAttribute("tabindex", "0");
var heading = this.create_element("div");
this.add_class(heading, "toc-heading");
heading.innerHTML = "Table of Contents".localize();
toc.appendChild(heading);
var previous = null;
for (var i = 0; i < this.slides.length; ++i)
{
var title = this.has_class(this.slides[i], "title");
var num = document.createTextNode((i + 1) + ". ");
toc.appendChild(num);
var a = this.create_element("a");
a.setAttribute("href", "#(" + (i+1) + ")");
if (title)
this.add_class(a, "titleslide");
var name = document.createTextNode(this.slide_name(i));
a.appendChild(name);
a.onclick = w3c_slidy.toc_click;
a.onkeydown = w3c_slidy.toc_keydown;
a.previous = previous;
if (previous)
previous.next = a;
toc.appendChild(a);
if (i == 0)
toc.first = a;
if (i < this.slides.length - 1)
{
var br = this.create_element("br");
toc.appendChild(br);
}
previous = a;
}
toc.focus = function () {
if (this.first)
this.first.focus();
}
toc.onmouseup = w3c_slidy.mouse_button_up;
toc.onclick = function (e) {
e||(e=window.event);
if (w3c_slidy.selected_text_len <= 0)
w3c_slidy.hide_table_of_contents();
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
};
document.body.insertBefore(toc, document.body.firstChild);
return toc;
},
is_shown_toc: function () {
return !w3c_slidy.has_class(w3c_slidy.toc, "hidden");
},
show_table_of_contents: function () {
w3c_slidy.remove_class(w3c_slidy.toc, "hidden");
var toc = w3c_slidy.toc;
toc.focus();
if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0)
setTimeout(w3c_slidy.ie_hack, 100);
},
hide_table_of_contents: function () {
w3c_slidy.add_class(w3c_slidy.toc, "hidden");
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
},
toggle_table_of_contents: function () {
if (w3c_slidy.is_shown_toc())
w3c_slidy.hide_table_of_contents();
else
w3c_slidy.show_table_of_contents();
},
// called on clicking toc entry
toc_click: function (e) {
if (!e)
e = window.event;
var target = w3c_slidy.get_target(e);
if (target && target.nodeType == 1)
{
var uri = target.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
}
w3c_slidy.hide_table_of_contents(e);
if (w3c_slidy.ie7) w3c_slidy.ie_hack();
w3c_slidy.stop_propagation(e);
return w3c_slidy.cancel(e);
},
// called onkeydown for toc entry
toc_keydown: function (event) {
var key;
if (!event)
var event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey)
return true;
if (key == 13)
{
var uri = this.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
w3c_slidy.hide_table_of_contents();
if (self.ie7)
w3c_slidy.ie_hack();
return w3c_slidy.cancel(event);
}
if (key == 40 && this.next)
{
this.next.focus();
return w3c_slidy.cancel(event);
}
if (key == 38 && this.previous)
{
this.previous.focus();
return w3c_slidy.cancel(event);
}
return true;
},
// ### OBSOLETE ###
before_print: function () {
this.show_all_slides();
this.hide_toolbar();
alert("before print");
},
// ### OBSOLETE ###
after_print: function () {
if (!this.view_all)
{
this.single_slide_view();
this.show_toolbar();
}
alert("after print");
},
// ### OBSOLETE ###
print_slides: function () {
this.before_print();
window.print();
this.after_print();
},
// ### OBSOLETE ?? ###
toggle_view: function () {
if (this.view_all)
{
this.single_slide_view();
this.show_toolbar();
this.view_all = 0;
}
else
{
this.show_all_slides();
this.hide_toolbar();
this.view_all = 1;
}
},
// prepare for printing ### OBSOLETE ###
show_all_slides: function () {
this.remove_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
},
// restore after printing ### OBSOLETE ###
single_slide_view: function () {
this.add_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
},
// suppress IE's image toolbar pop up
hide_image_toolbar: function () {
if (!this.ns_pos)
{
var images = document.getElementsByTagName("IMG");
for (var i = 0; i < images.length; ++i)
images[i].setAttribute("galleryimg", "no");
}
},
unloaded: function (e) {
//alert("unloaded");
},
// Safari and Konqueror don't yet support getComputedStyle()
// and they always reload page when location.href is updated
is_KHTML: function () {
var agent = navigator.userAgent;
return (agent.indexOf("KHTML") >= 0 ? true : false);
},
// find slide name from first h1 element
// default to document title + slide number
slide_name: function (index) {
var name = null;
var slide = this.slides[index];
var heading = this.find_heading(slide);
if (heading)
name = this.extract_text(heading);
if (!name)
name = this.title + "(" + (index + 1) + ")";
name.replace(/\&/g, "&amp;");
name.replace(/\</g, "&lt;");
name.replace(/\>/g, "&gt;");
return name;
},
// find first h1 element in DOM tree
find_heading: function (node) {
if (!node || node.nodeType != 1)
return null;
if (node.nodeName == "H1" || node.nodeName == "h1")
return node;
var child = node.firstChild;
while (child)
{
node = this.find_heading(child);
if (node)
return node;
child = child.nextSibling;
}
return null;
},
// recursively extract text from DOM tree
extract_text: function (node) {
if (!node)
return "";
// text nodes
if (node.nodeType == 3)
return node.nodeValue;
// elements
if (node.nodeType == 1)
{
node = node.firstChild;
var text = "";
while (node)
{
text = text + this.extract_text(node);
node = node.nextSibling;
}
return text;
}
return "";
},
// find copyright text from meta element
find_copyright: function () {
var name, content;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "copyright")
return content;
}
return null;
},
find_size_adjust: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "font-size-adjustment")
return 1 * content;
}
return 1;
},
// <meta name="duration" content="20" /> for 20 minutes
find_duration: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "duration")
return 60000 * content;
}
return null;
},
replace_by_non_breaking_space: function (str) {
for (var i = 0; i < str.length; ++i)
str[i] = 160;
},
// ### CHECK ME ### is use of "li" okay for text/html?
// for XHTML do we also need to specify namespace?
init_outliner: function () {
var items = document.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i)
{
var target = items[i];
if (!this.has_class(target.parentNode, "outline"))
continue;
target.onclick = this.outline_click;
/* ### more work needed for IE6
if (!this.ns_pos)
{
target.onmouseover = this.hover_outline;
target.onmouseout = this.unhover_outline;
}
*/
if (this.foldable(target))
{
target.foldable = true;
target.onfocus = function () {w3c_slidy.outline = this;};
target.onblur = function () {w3c_slidy.outline = null;};
if (!target.getAttribute("tabindex"))
target.setAttribute("tabindex", "0");
if (this.has_class(target, "expand"))
this.unfold(target);
else
this.fold(target);
}
else
{
this.add_class(target, "nofold");
target.visible = true;
target.foldable = false;
}
}
},
foldable: function (item) {
if (!item || item.nodeType != 1)
return false;
var node = item.firstChild;
while (node)
{
if (node.nodeType == 1 && this.is_block(node))
return true;
node = node.nextSibling;
}
return false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
fold: function (item) {
if (item)
{
this.remove_class(item, "unfolded");
this.add_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.add_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
unfold: function (item) {
if (item)
{
this.add_class(item, "unfolded");
this.remove_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.remove_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = true;
},
outline_click: function (e) {
if (!e)
e = window.event;
var rightclick = false;
var target = w3c_slidy.get_target(e);
while (target && target.visible == undefined)
target = target.parentNode;
if (!target)
return true;
if (e.which)
rightclick = (e.which == 3);
else if (e.button)
rightclick = (e.button == 2);
if (!rightclick && target.visible != undefined)
{
if (target.foldable)
{
if (target.visible)
w3c_slidy.fold(target);
else
w3c_slidy.unfold(target);
}
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
}
return false;
},
add_initial_prompt: function () {
var prompt = this.create_element("div");
prompt.setAttribute("class", "initial_prompt");
var p1 = this.create_element("p");
prompt.appendChild(p1);
p1.setAttribute("class", "help");
if (this.keyboardless)
p1.innerHTML = "Tap footer to move to next slide";
else
p1.innerHTML = "Space or Right Arrow to move to next " +
"slide, click help below for more details";
this.add_listener(prompt, "click", function (e) {
document.body.removeChild(prompt);
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
});
document.body.appendChild(prompt);
this.initial_prompt = prompt;
setTimeout(function() {document.body.removeChild(prompt);}, 5000);
},
add_toolbar: function () {
var counter, page;
this.toolbar = this.create_element("div");
this.toolbar.setAttribute("class", "toolbar");
// a reasonably behaved browser
if (this.ns_pos || !this.ie6)
{
var right = this.create_element("div");
right.setAttribute("style", "float: right; text-align: right");
counter = this.create_element("span")
counter.innerHTML = "slide".localize() + " n/m";
right.appendChild(counter);
this.toolbar.appendChild(right);
var left = this.create_element("div");
left.setAttribute("style", "text-align: left");
// global end of slide indicator
this.eos = this.create_element("span");
this.eos.innerHTML = "* ";
left.appendChild(this.eos);
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
left.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
left.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
left.appendChild(contents);
var gap2 = document.createTextNode(" ");
left.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.className = "copyright";
span.innerHTML = copyright;
left.appendChild(span);
}
this.toolbar.setAttribute("tabindex", "0");
this.toolbar.appendChild(left);
}
else // IE6 so need to work around its poor CSS support
{
this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute");
this.toolbar.style.zIndex = "200";
this.toolbar.style.width = "99.9%";
this.toolbar.style.height = "1.2em";
this.toolbar.style.top = "auto";
this.toolbar.style.bottom = "0";
this.toolbar.style.left = "0";
this.toolbar.style.right = "0";
this.toolbar.style.textAlign = "left";
this.toolbar.style.fontSize = "60%";
this.toolbar.style.color = "red";
this.toolbar.borderWidth = 0;
this.toolbar.className = "toolbar";
this.toolbar.style.background = "rgb(240,240,240)";
// would like to have help text left aligned
// and page counter right aligned, floating
// div's don't work, so instead use nested
// absolutely positioned div's.
var sp = this.create_element("span");
sp.innerHTML = "&nbsp;&nbsp;*&nbsp;";
this.toolbar.appendChild(sp);
this.eos = sp; // end of slide indicator
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
this.toolbar.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
this.toolbar.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:toggleTableOfContents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
this.toolbar.appendChild(contents);
var gap2 = document.createTextNode(" ");
this.toolbar.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.innerHTML = copyright;
span.style.color = "black";
span.style.marginLeft = "0.5em";
this.toolbar.appendChild(span);
}
counter = this.create_element("div")
counter.style.position = "absolute";
counter.style.width = "auto"; //"20%";
counter.style.height = "1.2em";
counter.style.top = "auto";
counter.style.bottom = 0;
counter.style.right = "0";
counter.style.textAlign = "right";
counter.style.color = "red";
counter.style.background = "rgb(240,240,240)";
counter.innerHTML = "slide".localize() + " n/m";
this.toolbar.appendChild(counter);
}
// ensure that click isn't passed through to the page
this.toolbar.onclick =
function (e) {
if (!e)
e = window.event;
var target = e.target;
if (!target && e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target && target.nodeType == 3)
target = target.parentNode;
w3c_slidy.stop_propagation(e);
if (target && target.nodeName.toLowerCase() != "a")
w3c_slidy.mouse_button_click(e);
};
this.slide_number_element = counter;
this.set_eos_status(false);
document.body.appendChild(this.toolbar);
},
// wysiwyg editors make it hard to use div elements
// e.g. amaya loses the div when you copy and paste
// this function wraps div elements around implicit
// slides which start with an h1 element and continue
// up to the next heading or div element
wrap_implicit_slides: function () {
var i, heading, node, next, div;
var headings = document.getElementsByTagName("h1");
if (!headings)
return;
for (i = 0; i < headings.length; ++i)
{
heading = headings[i];
if (heading.parentNode != document.body)
continue;
node = heading.nextSibling;
div = document.createElement("div");
this.add_class(div, "slide");
document.body.replaceChild(div, heading);
div.appendChild(heading);
while (node)
{
if (node.nodeType == 1 && // an element
(node.nodeName == "H1" ||
node.nodeName == "h1" ||
node.nodeName == "DIV" ||
node.nodeName == "div"))
break;
next = node.nextSibling;
node = document.body.removeChild(node);
div.appendChild(node);
node = next;
}
}
},
// return new array of all slides
collect_slides: function () {
var slides = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "slide"))
{
// add slide to collection
slides[slides.length] = div;
// hide each slide as it is found
this.add_class(div, "hidden");
// add dummy <br/> at end for scrolling hack
var node1 = document.createElement("br");
div.appendChild(node1);
var node2 = document.createElement("br");
div.appendChild(node2);
}
else if (this.has_class(div, "background"))
{ // work around for Firefox SVG reload bug
// which otherwise replaces 1st SVG graphic with 2nd
div.style.display = "block";
}
}
this.slides = slides;
},
// return new array of all <div class="handout">
collect_notes: function () {
var notes = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "handout"))
{
// add note to collection
notes[notes.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.notes = notes;
},
// return new array of all <div class="background">
// including named backgrounds e.g. class="background titlepage"
collect_backgrounds: function () {
var backgrounds = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "background"))
{
// add background to collection
backgrounds[backgrounds.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.backgrounds = backgrounds;
},
// set click handlers on all anchors
patch_anchors: function () {
var self = w3c_slidy;
var handler = function (event) {
// compare this.href with location.href
// for link to another slide in this doc
if (self.page_address(this.href) == self.page_address(location.href))
{
// yes, so find new slide number
var newslidenum = self.find_slide_number(this.href);
if (newslidenum != self.slide_number)
{
var slide = self.slides[self.slide_number];
self.hide_slide(slide);
self.slide_number = newslidenum;
slide = self.slides[self.slide_number];
self.show_slide(slide);
self.set_location();
}
}
else if (this.target == null)
location.href = this.href;
this.blur();
self.disable_slide_click = true;
};
var anchors = document.body.getElementsByTagName("a");
for (var i = 0; i < anchors.length; ++i)
{
if (window.addEventListener)
anchors[i].addEventListener("click", handler, false);
else
anchors[i].attachEvent("onclick", handler);
}
},
// ### CHECK ME ### see which functions are invoked via setTimeout
// either directly or indirectly for use of w3c_slidy vs this
show_slide_number: function () {
var timer = w3c_slidy.get_timer();
w3c_slidy.slide_number_element.innerHTML = timer + "slide".localize() + " " +
(w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length;
},
// every 200mS check if the location has been changed as a
// result of the user activating the Back button/menu item
// doesn't work for Opera < 9.5
check_location: function () {
var hash = location.hash;
if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#"))
w3c_slidy.goto_slide(0);
else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")")
{
var num = parseInt(location.hash.substr(2));
if (!isNaN(num))
w3c_slidy.goto_slide(num-1);
}
if (w3c_slidy.time_left && w3c_slidy.slide_number > 0)
{
w3c_slidy.show_slide_number();
if (w3c_slidy.time_left > 0)
w3c_slidy.time_left -= 200;
}
},
get_timer: function () {
var timer = "";
if (w3c_slidy.time_left)
{
var mins, secs;
secs = Math.floor(w3c_slidy.time_left/1000);
mins = Math.floor(secs / 60);
secs = secs % 60;
timer = (mins ? mins+"m" : "") + secs + "s ";
}
return timer;
},
// this doesn't push location onto history stack for IE
// for which a hidden iframe hack is needed: load page into
// the iframe with script that set's parent's location.hash
// but that won't work for standalone use unless we can
// create the page dynamically via a javascript: URL
set_location: function () {
var uri = w3c_slidy.page_address(location.href);
var hash = "#(" + (w3c_slidy.slide_number+1) + ")";
if (w3c_slidy.slide_number >= 0)
uri = uri + hash;
if (w3c_slidy.ie && !w3c_slidy.ie8)
w3c_slidy.push_hash(hash);
if (uri != location.href) // && !khtml
location.href = uri;
if (this.khtml)
hash = "(" + (w3c_slidy.slide_number+1) + ")";
if (!this.ie && location.hash != hash && location.hash != "")
location.hash = hash;
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide_number();
},
page_address: function (uri) {
var i = uri.indexOf("#");
if (i < 0)
i = uri.indexOf("%23");
// check if anchor is entire page
if (i < 0)
return uri; // yes
return uri.substr(0, i);
},
// only used for IE6 and IE7
on_frame_loaded: function (hash) {
location.hash = hash;
var uri = w3c_slidy.page_address(location.href);
location.href = uri + hash;
},
// history hack with thanks to Bertrand Le Roy
push_hash: function (hash) {
if (hash == "") hash = "#(1)";
window.location.hash = hash;
var doc = document.getElementById("historyFrame").contentWindow.document;
doc.open("javascript:'<html></html>'");
// PWL modified this string literal to break the close script tag
// which otherwise gets parsed when incorporated
doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+
(hash) + "');</" + "script></head><body>hello mum</body></html>");
doc.close();
},
// find current slide based upon location
// first find target anchor and then look
// for associated div element enclosing it
// finally map that to slide number
find_slide_number: function (uri) {
// first get anchor from page location
var i = uri.indexOf("#");
// check if anchor is entire page
if (i < 0)
return 0; // yes
var anchor = unescape(uri.substr(i+1));
// now use anchor as XML ID to find target
var target = document.getElementById(anchor);
if (!target)
{
// does anchor look like "(2)" for slide 2 ??
// where first slide is (1)
var re = /\((\d)+\)/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// accept [2] for backwards compatibility
re = /\[(\d)+\]/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// oh dear unknown anchor
return 0;
}
// search for enclosing slide
while (true)
{
// browser coerces html elements to uppercase!
if (target.nodeName.toLowerCase() == "div" &&
this.has_class(target, "slide"))
{
// found the slide element
break;
}
// otherwise try parent element if any
target = target.parentNode;
if (!target)
{
return 0; // no luck!
}
};
for (i = 0; i < slides.length; ++i)
{
if (slides[i] == target)
return i; // success
}
// oh dear still no luck
return 0;
},
previous_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide;
if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null)
{
w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown);
w3c_slidy.set_eos_status(false);
}
else if (w3c_slidy.slide_number > 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.set_eos_status(true);
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_location();
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
next_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide, last = w3c_slidy.last_shown;
if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1)
w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown);
if ((!incremental || w3c_slidy.last_shown == null) &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number + 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
else if (!w3c_slidy.last_shown)
{
if (last && incremental)
w3c_slidy.last_shown = last;
}
w3c_slidy.set_location();
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
// to first slide with nothing revealed
// i.e. state at start of presentation
first_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
if (w3c_slidy.slide_number != 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = 0;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_eos_status(
!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.set_location();
}
},
// goto last slide with everything revealed
// i.e. state at end of presentation
last_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
w3c_slidy.last_shown = null; //revealNextItem(lastShown);
if (w3c_slidy.last_shown == null &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slides.length - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.show_slide(slide);
}
else
{
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
}
w3c_slidy.set_eos_status(true);
w3c_slidy.set_location();
}
},
// ### check this and consider add/remove class
set_eos_status: function (state) {
if (this.eos)
this.eos.style.color = (state ? "rgb(240,240,240)" : "red");
},
// first slide is 0
goto_slide: function (num) {
//alert("going to slide " + (num+1));
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = num;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide(slide);
w3c_slidy.show_slide_number();
},
show_slide: function (slide) {
this.sync_background(slide);
window.scrollTo(0,0);
this.remove_class(slide, "hidden");
},
hide_slide: function (slide) {
this.add_class(slide, "hidden");
},
// show just the backgrounds pertinent to this slide
// when slide background-color is transparent
// this should now work with rgba color values
sync_background: function (slide) {
var background;
var bgColor;
if (slide.currentStyle)
bgColor = slide.currentStyle["backgroundColor"];
else if (document.defaultView)
{
var styles = document.defaultView.getComputedStyle(slide,null);
if (styles)
bgColor = styles.getPropertyValue("background-color");
else // broken implementation probably due Safari or Konqueror
{
//alert("defective implementation of getComputedStyle()");
bgColor = "transparent";
}
}
else
bgColor == "transparent";
if (bgColor == "transparent" ||
bgColor.indexOf("rgba") >= 0 ||
bgColor.indexOf("opacity") >= 0)
{
var slideClass = this.get_class_list(slide);
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
var bgClass = this.get_class_list(background);
if (this.matching_background(slideClass, bgClass))
this.remove_class(background, "hidden");
else
this.add_class(background, "hidden");
}
}
else // forcibly hide all backgrounds
this.hide_backgrounds();
},
hide_backgrounds: function () {
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
this.add_class(background, "hidden");
}
},
// compare classes for slide and background
matching_background: function (slideClass, bgClass) {
var i, count, pattern, result;
// define pattern as regular expression
pattern = /\w+/g;
// check background class names
result = bgClass.match(pattern);
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (result[i] == "background")
continue;
++count;
}
if (count == 0) // default match
return true;
// check for matches and place result in array
result = slideClass.match(pattern);
// now check if desired name is present for background
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (this.has_token(bgClass, result[i]))
return true;
}
return false;
},
resized: function () {
var width = 0;
if ( typeof( window.innerWidth ) == 'number' )
width = window.innerWidth; // Non IE browser
else if (document.documentElement && document.documentElement.clientWidth)
width = document.documentElement.clientWidth; // IE6
else if (document.body && document.body.clientWidth)
width = document.body.clientWidth; // IE4
var height = 0;
if ( typeof( window.innerHeight ) == 'number' )
height = window.innerHeight; // Non IE browser
else if (document.documentElement && document.documentElement.clientHeight)
height = document.documentElement.clientHeight; // IE6
else if (document.body && document.body.clientHeight)
height = document.body.clientHeight; // IE4
if (height && (width/height > 1.05*1024/768))
{
width = height * 1024.0/768;
}
// IE fires onresize even when only font size is changed!
// so we do a check to avoid blocking < and > actions
if (width != w3c_slidy.last_width || height != w3c_slidy.last_height)
{
if (width >= 1100)
w3c_slidy.size_index = 5; // 4
else if (width >= 1000)
w3c_slidy.size_index = 4; // 3
else if (width >= 800)
w3c_slidy.size_index = 3; // 2
else if (width >= 600)
w3c_slidy.size_index = 2; // 1
else if (width)
w3c_slidy.size_index = 0;
// add in font size adjustment from meta element e.g.
// <meta name="font-size-adjustment" content="-2" />
// useful when slides have too much content ;-)
if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment &&
w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length)
w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment;
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
w3c_slidy.adjust_object_dimensions(width, height);
if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index])
{
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
}
w3c_slidy.last_width = width;
w3c_slidy.last_height = height;
// force reflow to work around Mozilla bug
if (w3c_slidy.ns_pos)
{
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
}
// force correct positioning of toolbar
w3c_slidy.refresh_toolbar(200);
}
},
scrolled: function () {
if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset();
// hide toolbar
w3c_slidy.toolbar.style.display = "none";
// make it reappear later
if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all)
{
setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000);
w3c_slidy.scrollhack = 1;
}
}
},
hide_toolbar: function () {
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden");
window.focus();
},
// used to ensure IE refreshes toolbar in correct position
refresh_toolbar: function (interval) {
if (!w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hide_toolbar();
setTimeout(function () {w3c_slidy.show_toolbar(); }, interval);
}
},
// restores toolbar after short delay
show_toolbar: function () {
if (w3c_slidy.want_toolbar)
{
w3c_slidy.toolbar.style.display = "block";
if (!w3c_slidy.ns_pos)
{
// adjust position to allow for scrolling
var xoffset = w3c_slidy.scroll_x_offset();
w3c_slidy.toolbar.style.left = xoffset;
w3c_slidy.toolbar.style.right = xoffset;
// determine vertical scroll offset
//var yoffset = scrollYOffset();
// bottom is doc height - window height - scroll offset
//var bottom = documentHeight() - lastHeight - yoffset
//if (yoffset > 0 || documentHeight() > lastHeight)
// bottom += 16; // allow for height of scrollbar
w3c_slidy.toolbar.style.bottom = 0; //bottom;
}
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden");
}
w3c_slidy.scrollhack = 0;
// set the keyboard focus to the help link on the
// toolbar to ensure that document has the focus
// IE doesn't always work with window.focus()
// and this hack has benefit of Enter for help
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
},
// invoked via F key
toggle_toolbar: function () {
if (!w3c_slidy.view_all)
{
if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden"))
{
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 1;
}
else
{
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 0;
}
}
},
scroll_x_offset: function () {
if (window.pageXOffset)
return self.pageXOffset;
if (document.documentElement &&
document.documentElement.scrollLeft)
return document.documentElement.scrollLeft;
if (document.body)
return document.body.scrollLeft;
return 0;
},
scroll_y_offset: function () {
if (window.pageYOffset)
return self.pageYOffset;
if (document.documentElement &&
document.documentElement.scrollTop)
return document.documentElement.scrollTop;
if (document.body)
return document.body.scrollTop;
return 0;
},
// looking for a way to determine height of slide content
// the slide itself is set to the height of the window
optimize_font_size: function () {
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
//var dh = documentHeight(); //getDocHeight(document);
var dh = slide.scrollHeight;
var wh = getWindowHeight();
var u = 100 * dh / wh;
alert("window utilization = " + u + "% (doc "
+ dh + " win " + wh + ")");
},
// from document object
get_doc_height: function (doc) {
if (!doc)
doc = document;
if (doc && doc.body && doc.body.offsetHeight)
return doc.body.offsetHeight; // ns/gecko syntax
if (doc && doc.body && doc.body.scrollHeight)
return doc.body.scrollHeight;
alert("couldn't determine document height");
},
get_window_height: function () {
if ( typeof( window.innerHeight ) == 'number' )
return window.innerHeight; // Non IE browser
if (document.documentElement && document.documentElement.clientHeight)
return document.documentElement.clientHeight; // IE6
if (document.body && document.body.clientHeight)
return document.body.clientHeight; // IE4
},
document_height: function () {
var sh, oh;
sh = document.body.scrollHeight;
oh = document.body.offsetHeight;
if (sh && oh)
{
return (sh > oh ? sh : oh);
}
// no idea!
return 0;
},
smaller: function () {
if (w3c_slidy.size_index > 0)
{
--w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
bigger: function () {
if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1)
{
++w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
// with thanks to Ivan Herman for the suggestion
adjust_object_dimensions: function (width, height) {
for( var i = 0; i < w3c_slidy.objects.length; i++ )
{
var obj = this.objects[i];
var mimeType = obj.getAttribute("type");
if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
{
if ( !obj.initialWidth )
obj.initialWidth = obj.getAttribute("width");
if ( !obj.initialHeight )
obj.initialHeight = obj.getAttribute("height");
if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
{
var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
var newW = width * (w/100.0);
obj.setAttribute("width",newW);
}
if ( obj.initialHeight &&
obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
{
var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
var newH = height * (h/100.0);
obj.setAttribute("height", newH);
}
}
}
},
// needed for Opera to inhibit default behavior
// since Opera delivers keyPress even if keyDown
// was cancelled
key_press: function (event) {
if (!event)
event = window.event;
if (!w3c_slidy.key_wanted)
return w3c_slidy.cancel(event);
return true;
},
// See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
key_down: function (event) {
var key;
w3c_slidy.key_wanted = true;
if (!event)
event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey || event.metaKey)
return true;
// dismiss table of contents if visible
if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40)
{
w3c_slidy.hide_table_of_contents();
if (key == 27 || key == 84 || key == 67)
return w3c_slidy.cancel(event);
}
if (key == 34) // Page Down
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.next_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 33) // Page Up
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.previous_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 32) // space bar
{
w3c_slidy.next_slide(true);
return w3c_slidy.cancel(event);
}
else if (key == 37) // Left arrow
{
w3c_slidy.previous_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 36) // Home
{
w3c_slidy.first_slide();
return w3c_slidy.cancel(event);
}
else if (key == 35) // End
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 39) // Right arrow
{
w3c_slidy.next_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 13) // Enter
{
if (w3c_slidy.outline)
{
if (w3c_slidy.outline.visible)
w3c_slidy.fold(w3c_slidy.outline);
else
w3c_slidy.unfold(w3c_slidy.outline);
return w3c_slidy.cancel(event);
}
}
else if (key == 188) // < for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 190) // > for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 189 || key == 109) // - for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 83) // S for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 66) // B for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 90) // Z for last slide
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 70) // F for toggle toolbar
{
w3c_slidy.toggle_toolbar();
return w3c_slidy.cancel(event);
}
else if (key == 65) // A for toggle view single/all slides
{
w3c_slidy.toggle_view();
return w3c_slidy.cancel(event);
}
else if (key == 75) // toggle action of left click for next page
{
w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled;
var alert_msg = (w3c_slidy.mouse_click_enabled ?
"enabled" : "disabled") + " mouse click advance";
alert(alert_msg.localize());
return w3c_slidy.cancel(event);
}
else if (key == 84 || key == 67) // T or C for table of contents
{
if (w3c_slidy.toc)
w3c_slidy.toggle_table_of_contents();
return w3c_slidy.cancel(event);
}
else if (key == 72) // H for help
{
window.location = w3c_slidy.help_page;
return w3c_slidy.cancel(event);
}
//else alert("key code is "+ key);
return true;
},
// safe for both text/html and application/xhtml+xml
create_element: function (name) {
if (this.xhtml && (typeof document.createElementNS != 'undefined'))
return document.createElementNS("http://www.w3.org/1999/xhtml", name)
return document.createElement(name);
},
get_element_style: function (elem, IEStyleProp, CSSStyleProp) {
if (elem.currentStyle)
{
return elem.currentStyle[IEStyleProp];
}
else if (window.getComputedStyle)
{
var compStyle = window.getComputedStyle(elem, "");
return compStyle.getPropertyValue(CSSStyleProp);
}
return "";
},
// the string str is a whitespace separated list of tokens
// test if str contains a particular token, e.g. "slide"
has_token: function (str, token) {
if (str)
{
// define pattern as regular expression
var pattern = /\w+/g;
// check for matches
// place result in array
var result = str.match(pattern);
// now check if desired token is present
for (var i = 0; i < result.length; i++)
{
if (result[i] == token)
return true;
}
}
return false;
},
get_class_list: function (element) {
if (typeof element.className != 'undefined')
return element.className;
return element.getAttribute("class");
},
has_class: function (element, name) {
if (element.nodeType != 1)
return false;
var regexp = new RegExp("(^| )" + name + "\W*");
if (typeof element.className != 'undefined')
return regexp.test(element.className);
return regexp.test(element.getAttribute("class"));
},
remove_class: function (element, name) {
var regexp = new RegExp("(^| )" + name + "\W*");
var clsval = "";
if (typeof element.className != 'undefined')
{
clsval = element.className;
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.className = clsval;
}
}
else
{
clsval = element.getAttribute("class");
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.setAttribute("class", clsval);
}
}
},
add_class: function (element, name) {
if (!this.has_class(element, name))
{
if (typeof element.className != 'undefined')
element.className += " " + name;
else
{
var clsval = element.getAttribute("class");
clsval = clsval ? clsval + " " + name : name;
element.setAttribute("class", clsval);
}
}
},
// HTML elements that can be used with class="incremental"
// note that you can also put the class on containers like
// up, ol, dl, and div to make their contents appear
// incrementally. Upper case is used since this is what
// browsers report for HTML node names (text/html).
incremental_elements: null,
okay_for_incremental: function (name) {
if (!this.incremental_elements)
{
var inclist = new Array();
inclist["p"] = true;
inclist["pre"] = true;
inclist["li"] = true;
inclist["blockquote"] = true;
inclist["dt"] = true;
inclist["dd"] = true;
inclist["h2"] = true;
inclist["h3"] = true;
inclist["h4"] = true;
inclist["h5"] = true;
inclist["h6"] = true;
inclist["span"] = true;
inclist["address"] = true;
inclist["table"] = true;
inclist["tr"] = true;
inclist["th"] = true;
inclist["td"] = true;
inclist["img"] = true;
inclist["object"] = true;
this.incremental_elements = inclist;
}
return this.incremental_elements[name.toLowerCase()];
},
next_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.next_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1) // ELEMENT
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
previous_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.previous_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1)
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
// set visibility for all elements on current slide with
// a parent element with attribute class="incremental"
set_visibility_all_incremental: function (value) {
var node = this.next_incremental_item(null);
if (value == "hidden")
{
while (node)
{
w3c_slidy.add_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
else // value == "visible"
{
while (node)
{
w3c_slidy.remove_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
},
// reveal the next hidden item on the slide
// node is null or the node that was last revealed
reveal_next_item: function (node) {
node = w3c_slidy.next_incremental_item(node);
if (node && node.nodeType == 1) // an element
w3c_slidy.remove_class(node, "invisible");
return node;
},
// exact inverse of revealNextItem(node)
hide_previous_item: function (node) {
if (node && node.nodeType == 1) // an element
w3c_slidy.add_class(node, "invisible");
return this.previous_incremental_item(node);
},
// left to right traversal of root's content
next_node: function (root, node) {
if (node == null)
return root.firstChild;
if (node.firstChild)
return node.firstChild;
if (node.nextSibling)
return node.nextSibling;
for (;;)
{
node = node.parentNode;
if (!node || node == root)
break;
if (node && node.nextSibling)
return node.nextSibling;
}
return null;
},
// right to left traversal of root's content
previous_node: function (root, node) {
if (node == null)
{
node = root.lastChild;
if (node)
{
while (node.lastChild)
node = node.lastChild;
}
return node;
}
if (node.previousSibling)
{
node = node.previousSibling;
while (node.lastChild)
node = node.lastChild;
return node;
}
if (node.parentNode != root)
return node.parentNode;
return null;
},
previous_sibling_element: function (el) {
el = el.previousSibling;
while (el && el.nodeType != 1)
el = el.previousSibling;
return el;
},
next_sibling_element: function (el) {
el = el.nextSibling;
while (el && el.nodeType != 1)
el = el.nextSibling;
return el;
},
first_child_element: function (el) {
var node;
for (node = el.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1)
break;
}
return node;
},
first_tag: function (element, tag) {
var node;
if (!this.is_xhtml)
tag = tag.toUpperCase();
for (node = element.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1 && node.nodeName == tag)
break;
}
return node;
},
hide_selection: function () {
if (window.getSelection) // Firefox, Chromium, Safari, Opera
{
var selection = window.getSelection();
if (selection.rangeCount > 0)
{
var range = selection.getRangeAt(0);
range.collapse (false);
}
}
else // Internet Explorer
{
var textRange = document.selection.createRange ();
textRange.collapse (false);
}
},
get_selected_text: function () {
try
{
if (window.getSelection)
return window.getSelection().toString();
if (document.getSelection)
return document.getSelection().toString();
if (document.selection)
return document.selection.createRange().text;
}
catch (e)
{
}
return "";
},
// make note of length of selected text
// as this evaluates to zero in click event
mouse_button_up: function (e) {
w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length;
},
// right mouse button click is reserved for context menus
// it is more reliable to detect rightclick than leftclick
mouse_button_click: function (e) {
var rightclick = false;
var leftclick = false;
var middleclick = false;
var target;
if (!e)
var e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target.nodeType == 3)
target = target.parentNode;
if (e.which) // all browsers except IE
{
leftclick = (e.which == 1);
middleclick = (e.which == 2);
rightclick = (e.which == 3);
}
else if (e.button)
{
// Konqueror gives 1 for left, 4 for middle
// IE6 gives 0 for left and not 1 as I expected
if (e.button == 4)
middleclick = true;
// all browsers agree on 2 for right button
rightclick = (e.button == 2);
}
else leftclick = true;
/*
alert("you clicked over a " + target.nodeName + " element\n" +
"w3c_slidy.mouse_click_enabled = " + w3c_slidy.mouse_click_enabled + "\n" +
"leftclick = " + leftclick + "\n" +
"selected text length = " + w3c_slidy.selected_text_len);
//alert("selected text length = " + w3c_slidy.selected_text_len);
*/
if (w3c_slidy.selected_text_len > 0)
{
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
// dismiss table of contents
w3c_slidy.hide_table_of_contents();
// check if target is something that probably want's clicks
// e.g. a, embed, object, input, textarea, select, option
var tag = target.nodeName.toLowerCase();
if (w3c_slidy.mouse_click_enabled && leftclick &&
tag != "a" &&
tag != "embed" &&
tag != "object" &&
tag != "video" &&
tag != "input" &&
tag != "textarea" &&
tag != "select" &&
tag != "option" &&
!target.onclick)
{
w3c_slidy.next_slide(true);
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
},
get_key: function (e)
{
var key;
// kludge around NS/IE differences
if (typeof window.event != "undefined")
key = window.event.keyCode;
else if (e.which)
key = e.which;
return key;
},
get_target: function (e) {
var target;
if (!e)
e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
if (target.nodeType != 1)
target = target.parentNode;
return target;
},
// does display property provide correct defaults?
is_block: function (elem) {
var tag = elem.nodeName.toLowerCase();
return tag == "ol" || tag == "ul" || tag == "p" ||
tag == "li" || tag == "table" || tag == "pre" ||
tag == "h1" || tag == "h2" || tag == "h3" ||
tag == "h4" || tag == "h5" || tag == "h6" ||
tag == "blockquote" || tag == "address";
},
add_listener: function (element, event, handler) {
if (window.addEventListener)
element.addEventListener(event, handler, false);
else
element.attachEvent("on"+event, handler);
},
// used to prevent event propagation from field controls
stop_propagation: function (event) {
event = event ? event : window.event;
event.cancelBubble = true; // for IE
if (event.stopPropagation)
event.stopPropagation();
return true;
},
cancel: function (event) {
if (event)
{
event.cancel = true;
event.returnValue = false;
if (event.preventDefault)
event.preventDefault();
}
w3c_slidy.key_wanted = false;
return false;
}
};
// for each language define an associative array
// and also the help text which is longer
var w3c_slidy_i18n = {
strings_es: {
"slide":"pág.",
"help?":"Ayuda",
"contents?":"Índice",
"table of contents":"tabla de contenidos",
"Table of Contents":"Tabla de Contenidos",
"restart presentation":"Reiniciar presentación",
"restart?":"Inicio"
},
help_es:
"Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
"o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.",
strings_ca: {
"slide":"pàg..",
"help?":"Ajuda",
"contents?":"Índex",
"table of contents":"taula de continguts",
"Table of Contents":"Taula de Continguts",
"restart presentation":"Reiniciar presentació",
"restart?":"Inici"
},
help_ca:
"Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
"o Re pàg y Av pàg. Usi S i B per canviar grandària de font.",
strings_cs: {
"slide":"snímek",
"help?":"nápověda",
"contents?":"obsah",
"table of contents":"obsah prezentace",
"Table of Contents":"Obsah prezentace",
"restart presentation":"znovu spustit prezentaci",
"restart?":"restart"
},
help_cs:
"Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " +
"šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " +
"dá zvětšit a zmenšit pomocí kláves B a S.",
strings_nl: {
"slide":"pagina",
"help?":"Help?",
"contents?":"Inhoud?",
"table of contents":"inhoudsopgave",
"Table of Contents":"Inhoudsopgave",
"restart presentation":"herstart presentatie",
"restart?":"Herstart?"
},
help_nl:
"Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
"of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.",
strings_de: {
"slide":"Seite",
"help?":"Hilfe",
"contents?":"Übersicht",
"table of contents":"Inhaltsverzeichnis",
"Table of Contents":"Inhaltsverzeichnis",
"restart presentation":"Präsentation neu starten",
"restart?":"Neustart"
},
help_de:
"Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
"Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.",
strings_pl: {
"slide":"slajd",
"help?":"pomoc?",
"contents?":"spis treści?",
"table of contents":"spis treści",
"Table of Contents":"Spis Treści",
"restart presentation":"Restartuj prezentację",
"restart?":"restart?"
},
help_pl:
"Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
"lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.",
strings_fr: {
"slide":"page",
"help?":"Aide",
"contents?":"Index",
"table of contents":"table des matières",
"Table of Contents":"Table des matières",
"restart presentation":"Recommencer l'exposé",
"restart?":"Début"
},
help_fr:
"Naviguez avec la souris, la barre d'espace, les flèches " +
"gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
"les touches S et B pour modifier la taille de la police.",
strings_hu: {
"slide":"oldal",
"help?":"segítség",
"contents?":"tartalom",
"table of contents":"tartalomjegyzék",
"Table of Contents":"Tartalomjegyzék",
"restart presentation":"bemutató újraindítása",
"restart?":"újraindítás"
},
help_hu:
"Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
"használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
"Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
"a szöveg méretét.",
strings_it: {
"slide":"pag.",
"help?":"Aiuto",
"contents?":"Indice",
"table of contents":"indice",
"Table of Contents":"Indice",
"restart presentation":"Ricominciare la presentazione",
"restart?":"Inizio"
},
help_it:
"Navigare con mouse, barra spazio, frecce sinistra/destra o " +
"PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.",
strings_el: {
"slide":"σελίδα",
"help?":"βοήθεια;",
"contents?":"περιεχόμενα;",
"table of contents":"πίνακας περιεχομένων",
"Table of Contents":"Πίνακας Περιεχομένων",
"restart presentation":"επανεκκίνηση παρουσίασης",
"restart?":"επανεκκίνηση;"
},
help_el:
"Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
"ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
"το μέγεθος της γραμματοσειράς.",
strings_ja: {
"slide":"スライド",
"help?":"ヘルプ",
"contents?":"目次",
"table of contents":"目次を表示",
"Table of Contents":"目次",
"restart presentation":"最初から再生",
"restart?":"最初から"
},
help_ja:
"マウス左クリック ・ スペース ・ 左右キー " +
"または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更",
strings_zh: {
"slide":"幻灯片",
"help?":"帮助?",
"contents?":"内容?",
"table of contents":"目录",
"Table of Contents":"目录",
"restart presentation":"重新启动展示",
"restart?":"重新启动?"
},
help_zh:
"用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
"用 S, B 改变字体大小.",
strings_ru: {
"slide":"слайд",
"help?":"помощь?",
"contents?":"содержание?",
"table of contents":"оглавление",
"Table of Contents":"Оглавление",
"restart presentation":"перезапустить презентацию",
"restart?":"перезапуск?"
},
help_ru:
"Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
"влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.",
strings_sv: {
"slide":"sida",
"help?":"hjälp",
"contents?":"innehåll",
"table of contents":"innehållsförteckning",
"Table of Contents":"Innehållsförteckning",
"restart presentation":"visa presentationen från början",
"restart?":"börja om"
},
help_sv:
"Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " +
"vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " +
"Använd tangenterna S och B för att ändra textens storlek.",
// each such language array is declared in the localize array
// which is set on string prototype and used as in "foo".localize();
localize: {
"es":this.strings_es,
"ca":this.strings_ca,
"cs":this.strings_cs,
"nl":this.strings_nl,
"de":this.strings_de,
"pl":this.strings_pl,
"fr":this.strings_fr,
"hu":this.strings_hu,
"it":this.strings_it,
"el":this.strings_el,
"jp":this.strings_ja,
"zh":this.strings_zh,
"ru":this.strings_ru,
"sv":this.strings_sv
},
init: function () {
var i18n = w3c_slidy_i18n;
var help_text = w3c_slidy.help_text;
i18n.strings_es[help_text] = i18n.help_es;
i18n.strings_ca[help_text] = i18n.help_ca;
i18n.strings_cs[help_text] = i18n.help_cs;
i18n.strings_nl[help_text] = i18n.help_nl;
i18n.strings_de[help_text] = i18n.help_de;
i18n.strings_pl[help_text] = i18n.help_pl;
i18n.strings_fr[help_text] = i18n.help_fr;
i18n.strings_hu[help_text] = i18n.help_hu;
i18n.strings_it[help_text] = i18n.help_it;
i18n.strings_el[help_text] = i18n.help_el;
i18n.strings_ja[help_text] = i18n.help_ja;
i18n.strings_zh[help_text] = i18n.help_zh;
i18n.strings_ru[help_text] = i18n.help_ru;
i18n.strings_sv[help_text] = i18n.help_sv;
w3c_slidy.lang = document.body.parentNode.getAttribute("lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = "en";
// add localize method to all strings
// for use as in "contents".localize()
String.prototype.localize = function() {
if (this == "")
return this;
// try full language code, e.g. en-US
var s, lookup = w3c_slidy_i18n.localize[w3c_slidy.lang];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
// strip country code suffix, e.g.
// try en if undefined for en-US
var lg = w3c_slidy.lang.split("-");
if (lg.length > 1)
{
lookup = w3c_slidy_i18n.localize[lg[0]];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
}
// otherwise string as is
return this;
};
}
};
// hack for back button behavior
if (w3c_slidy.ie6 || w3c_slidy.ie7)
{
document.write("<iframe id='historyFrame' " +
"src='javascript:\"<html"+"></"+"html>\"' " +
"height='1' width='1' " +
"style='position:absolute;left:-800px'></iframe>");
}
// attach event listeners for initialization
w3c_slidy.set_up();
// hide the slides as soon as body element is available
// to reduce annoying screen mess before the onload event
setTimeout(w3c_slidy.hide_slides, 50);
/*]]>*/
</script>
</head>
<body class="article">
<div id="header" class="slide">
<h1>JavaScript III - Constructor Functions and the <tt>this</tt> Keyword</h1>
<span id="author">Bruce Harris, 8/7/12</span><br />
</div>
<div class="sect1 slide">
<h1 id="_content_and_target_audience">Content and target audience</h1>
<div class="sectionbody">
<div class="paragraph"><p><strong>JavaScript III - Constructor Functions and the <tt>this</tt> Keyword</strong></p></div>
<div class="paragraph"><p>Digging into object oriented programing in JavaScript.</p></div>
<div class="paragraph"><p>Prototypes and object inheritance will be covered in later talks.</p></div>
<div class="paragraph"><p>You are familiar with basics of functional programming and working with
objects in JavaScript
(covered in
<a href="http://bruceharris.net/techtalks">JavaScript I - Variables, Functions, and Scope</a> and
<a href="http://bruceharris.net/techtalks">JavaScript II - Objects, Arrays, and Booleans</a>)</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_resources_and_tools">Resources and tools</h1>
<div class="sectionbody">
<ul class="">
<li>
<span>
These slides: <a href="http://bruceharris.net/techtalks/">http://bruceharris.net/techtalks</a>
</span>
</li>
<li>
<span>
Sandboxes: <a href="http://codepen.io/pen">CodePen</a>, <a href="http://jsfiddle.net/">JSFiddle</a>, <a href="http://jsbin.com/">JS Bin</a>
</span>
</li>
<li>
<span>
Use your browser&#8217;s debugger / developer tools
</span>
</li>
<li>
<span>
Reference: <a href="https://developer.mozilla.org/en/JavaScript/">Mozilla Developer Network</a>
</span>
</li>
<li>
<span>
Instruction (online book): <a href="http://eloquentjavascript.net/contents.html">Eloquent JavaScript</a>
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_not_as_i_do_8230">Not as I do&#8230;</h1>
<div class="sectionbody">
<div class="paragraph"><p>Avoid <tt>document.writeln()</tt> - not useful in real life, but useful for examples</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_the_tt_this_tt_keyword">The <tt>this</tt> keyword</h1>
<div class="sectionbody">
<div class="paragraph"><p><strong>What does it mean?</strong></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_this_tt_in_global_scope"><tt>this</tt> in global scope</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span> <span class="o">===</span> <span class="nb">window</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_this_tt_in_functions"><tt>this</tt> in functions</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_this_tt_in_functions_2"><tt>this</tt> in functions</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="nx">f</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_this_tt_in_function_invoked_as_em_method_em"><tt>this</tt> in function invoked as <em>method</em></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="nx">f</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_this_tt_in_function_invoked_as_em_method_em_2"><tt>this</tt> in function invoked as <em>method</em></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_this_tt_in_function_invoked_as_em_method_em_3"><tt>this</tt> in function invoked as <em>method</em></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">+=</span> <span class="mi">10</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="nx">o</span><span class="o">:</span> <span class="p">{</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">3</span> <span class="p">}</span>
<span class="p">};</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span> <span class="o">=</span> <span class="nx">f</span><span class="p">;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">m</span> <span class="o">=</span> <span class="nx">f</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_invocation_patterns_seen_thus_far_8230">Function invocation patterns seen thus far&#8230;</h1>
<div class="sectionbody">
<ul class="">
<li>
<span>
function: <tt>f();</tt>
</span>
</li>
<li>
<span>
method: <tt>o.f();</tt>
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_constructor_functions_and_the_tt_new_tt_operator">Constructor functions and the <tt>new</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_constructor_functions_and_the_tt_new_tt_operator_2">Constructor functions and the <tt>new</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="c1">// var this = {};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="c1">// return this;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_constructor_functions_and_the_tt_new_tt_operator_3">Constructor functions and the <tt>new</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_constructor_functions_and_the_tt_new_tt_operator_4">Constructor functions and the <tt>new</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_constructor_functions_and_the_tt_new_tt_operator_5">Constructor functions and the <tt>new</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_invocation_patterns_seen_thus_far_8230_2">Function invocation patterns seen thus far&#8230;</h1>
<div class="sectionbody">
<ul class="">
<li>
<span>
function: <tt>f();</tt>
</span>
</li>
<li>
<span>
method: <tt>o.f();</tt>
</span>
</li>
<li>
<span>
constructor: <tt>x = new F;</tt> or <tt>x = new F();</tt>
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_invocation_patterns_seen_thus_far_8230_3">Function invocation patterns seen thus far&#8230;</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">C</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">3</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="nx">C</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">C</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">m</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">C</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_functions_are_objects">Functions are objects</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">f</span><span class="p">.</span><span class="nx">z</span> <span class="o">===</span> <span class="s1">&#39;function&#39;</span><span class="p">)</span> <span class="nx">f</span><span class="p">.</span><span class="nx">z</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s1">&#39;&lt;hr&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">z</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_apply_tt_function_invocation_pattern"><tt>apply</tt> function invocation pattern</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">2</span> <span class="p">};</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">o</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_apply_tt_function_invocation_pattern_2"><tt>apply</tt> function invocation pattern</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">o1</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">m</span><span class="o">:</span> <span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">o2</span> <span class="o">=</span> <span class="p">{</span> <span class="nx">x</span><span class="o">:</span> <span class="mi">3</span> <span class="p">};</span>
<span class="nx">o1</span><span class="p">.</span><span class="nx">m</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">o2</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o1</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o2</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_passing_arguments_with_tt_apply_tt">Passing arguments with <tt>apply</tt></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">_x</span><span class="p">,</span> <span class="nx">_y</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="nx">_x</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="nx">_y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">y</span><span class="o">:</span> <span class="mi">2</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_tt_call_tt_is_similar_to_tt_apply_tt"><tt>call</tt> is similar to <tt>apply</tt></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">_x</span><span class="p">,</span> <span class="nx">_y</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="nx">_x</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">y</span> <span class="o">=</span> <span class="nx">_y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">x</span><span class="o">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="nx">y</span><span class="o">:</span> <span class="mi">2</span>
<span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;|&#39;</span> <span class="o">+</span> <span class="nx">o</span><span class="p">.</span><span class="nx">y</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_contexts_affecting_meaning_of_tt_this_tt_comprehensive_list">Contexts affecting meaning of <tt>this</tt> (comprehensive list)</h1>
<div class="sectionbody">
<div class="hdlist"><table>
<tr>
<td class="hdlist1">
In global scope
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
global object
</p>
</td>
</tr>
</table></div>
<div class="paragraph"><p><strong>In functions - depends on invocation pattern</strong></p></div>
<div class="hdlist"><table>
<tr>
<td class="hdlist1">
function
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
global object
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
method
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
object the function is a method of
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
constructor
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
new object returned by constructor
</p>
</td>
</tr>
<tr>
<td class="hdlist1">
<tt>apply</tt> or <tt>call</tt>
<br />
</td>
<td class="hdlist2">
<p style="margin-top: 0;">
the specified object
</p>
</td>
</tr>
</table></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_objects_with_methods_and_private_variables">Objects with methods and private variables</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCounter</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">reset</span><span class="p">(</span><span class="nx">newCount</span><span class="p">){</span>
<span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">current</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">count</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="nx">reset</span><span class="o">:</span> <span class="nx">reset</span><span class="p">,</span>
<span class="nx">current</span><span class="o">:</span> <span class="nx">current</span><span class="p">,</span>
<span class="nx">increment</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_objects_with_methods_operating_on_public_properties">Objects with methods operating on public properties</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">Counter</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">newCount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">increment</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Counter</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
<span class="nx">c</span><span class="p">.</span><span class="nx">increment</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
<span class="nx">c</span><span class="p">.</span><span class="nx">reset</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_method_chaining">Method chaining</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">Counter</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">reset</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">newCount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">=</span> <span class="nx">newCount</span> <span class="o">||</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">increment</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">amount</span> <span class="o">===</span> <span class="s1">&#39;undefined&#39;</span><span class="p">)</span> <span class="nx">amount</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">count</span> <span class="o">+=</span> <span class="nx">amount</span><span class="p">;</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Counter</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">increment</span><span class="p">().</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">reset</span><span class="p">().</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">reset</span><span class="p">(</span><span class="mi">5</span><span class="p">).</span><span class="nx">increment</span><span class="p">(</span><span class="mi">10</span><span class="p">).</span><span class="nx">count</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_1">Exercise 1</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">Customer</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">account</span><span class="p">){</span>
<span class="cm">/****</span>
<span class="cm"> your code here</span>
<span class="cm"> Customer is a constructor function</span>
<span class="cm"> customer object has...</span>
<span class="cm"> - a public name property containing the customer&#39;s name</span>
<span class="cm"> - a public account property containing the customer&#39;s account number</span>
<span class="cm"> - a public orders property containing the customer&#39;s orders (as an array)</span>
<span class="cm"> - info about orders directly accessible via the orders property</span>
<span class="cm"> - an addOrder method that takes 1 argument: order number</span>
<span class="cm"> */</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bob</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Customer</span><span class="p">(</span><span class="s1">&#39;Bob&#39;</span><span class="p">,</span> <span class="mi">5673</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span> <span class="c1">// 5673</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90023</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023]</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90028</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023, 90028]</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_2">Exercise 2</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">HTMLformatter</span><span class="p">(</span><span class="nx">content</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="c1">// HTMLformatter is a constructor function</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HTMLformatter</span><span class="p">(</span><span class="s2">&quot;hi&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">text</span><span class="p">);</span> <span class="c1">// hi</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">text</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">bold</span><span class="p">());</span> <span class="c1">// &lt;strong&gt;hello&lt;/strong&gt;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">italic</span><span class="p">());</span> <span class="c1">// &lt;em&gt;hello&lt;/em&gt;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">bold</span><span class="p">().</span><span class="nx">italic</span><span class="p">());</span> <span class="c1">// &lt;em&gt;&lt;strong&gt;hello&lt;/strong&gt;&lt;/em&gt;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_3">Exercise 3</h1>
<div class="sectionbody">
<div class="paragraph"><p>Rudimentary inheritance - objects that share methods</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">HTMLformatter</span><span class="p">(</span><span class="nx">content</span><span class="p">){</span>
<span class="c1">// your code here (leave intact from exercise 2)</span>
<span class="p">}</span>
<span class="c1">// feel free to add code in between / before / after</span>
<span class="kd">function</span> <span class="nx">HTMLformatter2</span><span class="p">(</span><span class="nx">content</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="c1">// HTMLformatter2 does everything HTMLformatter does, but adds the box method</span>
<span class="c1">// Avoid repeating code for methods already defined in HTMLformatter</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">HTMLformatter2</span><span class="p">(</span><span class="s2">&quot;hi&quot;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">text</span><span class="p">);</span> <span class="c1">// hi</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">text</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">box</span><span class="p">());</span> <span class="c1">// &lt;div style=&quot;border: 1px solid black;&quot;&gt;hello&lt;/div&gt;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">.</span><span class="nx">italic</span><span class="p">().</span><span class="nx">box</span><span class="p">());</span> <span class="c1">// &lt;div style=&quot;border: 1px solid black;&quot;&gt;&lt;em&gt;hello&lt;/em&gt;&lt;/div&gt;</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_4">Exercise 4</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">account</span><span class="p">){</span>
<span class="cm">/****</span>
<span class="cm"> your code here</span>
<span class="cm"> makeCustomer is NOT a constructor function (we do not use the new operator)</span>
<span class="cm"> but accomplishes the same as the constructor function in Exercise 1</span>
<span class="cm"> hint: think about the approach used to create objects in Session II</span>
<span class="cm"> customer object has...</span>
<span class="cm"> - a public name property containing the customer&#39;s name</span>
<span class="cm"> - a public account property containing the customer&#39;s account number</span>
<span class="cm"> - a public orders property containing the customer&#39;s orders (as an array)</span>
<span class="cm"> - info about orders directly accessible via the orders property</span>
<span class="cm"> - an addOrder method that takes 1 argument: order number</span>
<span class="cm"> */</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bob</span> <span class="o">=</span> <span class="nx">makeCustomer</span><span class="p">(</span><span class="s1">&#39;Bob&#39;</span><span class="p">,</span> <span class="mi">5673</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">account</span><span class="p">);</span> <span class="c1">// 5673</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90023</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023]</span>
<span class="nx">bob</span><span class="p">.</span><span class="nx">addOrder</span><span class="p">(</span><span class="mi">90028</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">bob</span><span class="p">.</span><span class="nx">orders</span><span class="p">);</span> <span class="c1">// [90023, 90028]</span>
</pre></div></div></div>
</div>
</div>
</body>
</html>

JavaScript I - Variables, Functions, and Scope

Content and Target Audience

Emphasis on behavior/syntax specific to JavaScript (as compared to other languages).

JavaScript experience not required, but you have experience programming in a C style language.

Output of code snippet below is obvious to you.

var i;
for (i = 0; i < 10; i++) {
    if (i % 2 == 0) {
        document.writeln(i); // document.writeln is a printing function
    }
    else {
        document.writeln(", ");
    }
}

Resources and Tools

Not as I do…​

Avoid document.writeln() - not useful in real life, but useful for examples

The var keyword

var x = 1;
document.writeln(x);

Is var Optional?

x = 1; // hmmmmmm.....
document.writeln(x);

Above code works, but is evil. Assigning variables without declaration using var creates global variables regardless of where they are declared (this is usually a very bad thing).

The typeof operator

var x = 1, s = "hello";
document.writeln(typeof x);
document.writeln(typeof s);

Dynamic Typing

var x = 1;
document.writeln(typeof x);

x = "hello";  // can we change a number to a string?
document.writeln(typeof x);

x = 1.1;      // is a decimal different from an integer?
document.writeln(typeof x);

Function Statement

function print(x){
    document.writeln(x + '<br>');
} // note no semicolon
print("hello");
print("world");

Function Expression

// anonymous function
function (x) {
    document.writeln(x + '<br>');
};
// capture function in variable
var print = function (x) {
    document.writeln(x + '<br>');
};
print("hello");
print("world");

Passing a Function as an Argument to Another Function

var print = function (x) {
    document.writeln(x + '<br>');
};
var italic = function (x) {
    return '<em>' + x + '</em>';
};
function callFunc(fn, arg){
    fn(arg);
}

callFunc(print, "hello");
print(italic("world"));

Returning a function from a function

var print = function (x) {
    document.writeln(x + '<br>');
};
var italic = function (x) {
    return '<em>' + x + '</em>';
};
function makeCompoundFunction(outer, inner){
    return function(arg){
        outer(inner(arg));
    };
}
var printItalic = makeCompoundFunction(print, italic);

print("hello");
printItalic("world");

Block Scope v. Function Scope

Most C style languages have block scope.

var x = 1;
if (true) {
    var x = 2; // did we change x or create a new x?
    document.writeln(x);
}
document.writeln(x);

Function Scope

JavaScript does not have block scope, it has only function scope

var x = 1;
function f() {
    var x = 2; // did we change x or create a new x?
    document.writeln(x);
}
document.writeln(x);
f();
document.writeln(x);

Lexical Scoping v. Dynamic Scoping

Most C style languages have Lexical Scoping. So does JavaScript.

  • Every function creates its own scope environment

  • Variables declared inside a function are…​

    • visible everywhere inside that function

    • not visible outside that function

  • Variables (or functions) declared outside of any function are global

More specifically…​

  • In JavaScript functions can be nested inside other functions

  • A function has access to the scope environment of its parent function(s)

  • Thus, variables declared inside a function are visible inside functions nested inside the same function

Closure

  • Scope environment created by a function can persist even after function finishes executing

Declare x in global scope

var x = 1;

function f(){
    x = 2;
    document.writeln(x);
}
document.writeln(x);
f();
document.writeln(x);

Declare x in function scope

function f(){
    var x = 2;
}
f();
document.writeln(x); // will this work?

Declare x in global scope and in function scope

var x = 1;

function f(){
    var x = 2;
    document.writeln(x);
}
document.writeln(x);
f();
document.writeln(x);

Declare x in global scope and as function parameter

var x = 1;

function f(x){
    x = 2;
    document.writeln(x);
}
document.writeln(x);
f();
document.writeln(x);

Reference x in function scope without var keyword

function f(){
    x = 2; // is this a good idea?
    document.writeln(x);
}
f();
document.writeln(x); // will this work?

Declare nested function and call it outside

var x = 1;

function f1(){
    var x = 2;
    function f2(){
        document.writeln(x);
    }
}
f2(); // will this work?
document.writeln(x);

Declare nested function and call it inside

var x = 1;

function f1(){
    var x = 2;
    function f2(){
        document.writeln(x);
    }
    f2();
}
document.writeln(x);
f1();
document.writeln(x);

Closure

Environment created by invoking a function persists even after function is finished executing.

function makeAccumulator(){
    var x = 0;
    return function (n) {
	x += n;
        return x;
    };
}
var accum = makeAccumulator();
document.writeln(accum(5));
document.writeln(accum(4));
document.writeln(accum(13));

Closure creates a new persistent environment

function makeAccumulator(){
    var x = 0;
    return function (n) {
	x += n;
        return x;
    };
}
var accum1 = makeAccumulator();
document.writeln(accum1(5));
document.writeln(accum1(4));

var accum2 = makeAccumulator();
document.writeln(accum2(23));
document.writeln(accum2(17));

Function Hoisting

Most important difference between function statements and function expressions:

Function statements are "hoisted" to the top of the scope in which they appear. Regardless of where they appear within a scope environment, it is as if they were declared at the top of that scope environment.

Function expressions are not hoisted.

var f1;
f1(); // can we call f1 before function expression assignment?
f1 = function () {
    document.writeln(1);
};

f2(); // can we call f2 before its declaration via function statement?
function f2(){
    document.writeln(2);
}

Function expressions are not hoisted

var f;
f = function () { return 2; };
document.writeln(f());

f = function () { return 1; };
document.writeln(f());

Hoisting can cause unintuitive behavior

var f;
f = function(){ return 2; };
document.writeln(f());

function f(){ return 1 }
document.writeln(f()); // did we re-assign f?

Immediate function

(function(){
    var s = "cool, no global variables!";
    document.writeln(s);
})(); // anonymous function invoked immediately

Exercise 1

function makeAdder(x){
    // your code here
}

var add7 = makeAdder(7);
document.writeln(add7(4)); // 11
document.writeln(add7(9)); // 16

var add3 = makeAdder(3);
document.writeln(add3(6)); // 9
document.writeln(add3(2)); // 5

Exercise 2

Not practical, but a good exercise in functional programming

var sum1 = // your code here
document.writeln(sum1(3, 4)());  // 7

var sum2 = // your code here
document.writeln(sum2()(3, 4));  // 7

Exercise 3

function makeCounter(start, increment){
    // your code here
}

var counter1 = makeCounter(100, 1);
document.writeln(counter1()); // 100
document.writeln(counter1()); // 101

var counter2 = makeCounter(10, 5);
document.writeln(counter2()); // 10
document.writeln(counter2()); // 15

Exercise 4

function add(x, y){
    return x + y;
}
function subtract(x, y){
    return x - y;
}
// operation is either '+' or '-'
function makeReducer(operation){
    // your code here, preferably just one line
}

var plus = makeReducer('+');
document.writeln(plus(4, 5)); // 9

var minus = makeReducer('-');
document.writeln(minus(4, 5)); // -1

Exercise 5

Modify solution to Exercise 4 to remove add and subtract from the global scope

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="AsciiDoc 8.6.7">
<title>JavaScript I - Variables, Functions, and Scope</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
pre {
padding: 0;
margin: 0;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
tt {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
.monospaced {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/*
pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = { // Namespace.
/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////
/* Author: Mihai Bazon, September 2002
* http://students.infoiasi.ro/~mishoo
*
* Table Of Content generator
* Version: 0.4
*
* Feel free to use this script under the terms of the GNU General Public
* License, as long as you do not remove or alter this notice.
*/
/* modified by Troy D. Hanson, September 2006. License: GPL */
/* modified by Stuart Rackham, 2006, 2009. License: GPL */
// toclevels = 1..4.
toc: function (toclevels) {
function getText(el) {
var text = "";
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
text += i.data;
else if (i.firstChild != null)
text += getText(i);
}
return text;
}
function TocEntry(el, text, toclevel) {
this.element = el;
this.text = text;
this.toclevel = toclevel;
}
function tocEntries(el, toclevels) {
var result = new Array;
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
// Function that scans the DOM tree for header elements (the DOM2
// nodeIterator API would be a better technique but not supported by all
// browsers).
var iterate = function (el) {
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
var mo = re.exec(i.tagName);
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
}
iterate(i);
}
}
}
iterate(el);
return result;
}
var toc = document.getElementById("toc");
if (!toc) {
return;
}
// Delete existing TOC entries in case we're reloading the TOC.
var tocEntriesToRemove = [];
var i;
for (i = 0; i < toc.childNodes.length; i++) {
var entry = toc.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div'
&& entry.getAttribute("class")
&& entry.getAttribute("class").match(/^toclevel/))
tocEntriesToRemove.push(entry);
}
for (i = 0; i < tocEntriesToRemove.length; i++) {
toc.removeChild(tocEntriesToRemove[i]);
}
// Rebuild TOC entries.
var entries = tocEntries(document.getElementById("content"), toclevels);
for (var i = 0; i < entries.length; ++i) {
var entry = entries[i];
if (entry.element.id == "")
entry.element.id = "_toc_" + i;
var a = document.createElement("a");
a.href = "#" + entry.element.id;
a.appendChild(document.createTextNode(entry.text));
var div = document.createElement("div");
div.appendChild(a);
div.className = "toclevel" + entry.toclevel;
toc.appendChild(div);
}
if (entries.length == 0)
toc.parentNode.removeChild(toc);
},
/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////
/* Based on footnote generation code from:
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
*/
footnotes: function () {
// Delete existing footnote entries in case we're reloading the footnodes.
var i;
var noteholder = document.getElementById("footnotes");
if (!noteholder) {
return;
}
var entriesToRemove = [];
for (i = 0; i < noteholder.childNodes.length; i++) {
var entry = noteholder.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
entriesToRemove.push(entry);
}
for (i = 0; i < entriesToRemove.length; i++) {
noteholder.removeChild(entriesToRemove[i]);
}
// Rebuild footnote entries.
var cont = document.getElementById("content");
var spans = cont.getElementsByTagName("span");
var refs = {};
var n = 0;
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnote") {
n++;
var note = spans[i].getAttribute("data-note");
if (!note) {
// Use [\s\S] in place of . so multi-line matches work.
// Because JavaScript has no s (dotall) regex flag.
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
spans[i].innerHTML =
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
spans[i].setAttribute("data-note", note);
}
noteholder.innerHTML +=
"<div class='footnote' id='_footnote_" + n + "'>" +
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
n + "</a>. " + note + "</div>";
var id =spans[i].getAttribute("id");
if (id != null) refs["#"+id] = n;
}
}
if (n == 0)
noteholder.parentNode.removeChild(noteholder);
else {
// Process footnoterefs.
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnoteref") {
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
href = href.match(/#.*/)[0]; // Because IE return full URL.
n = refs[href];
spans[i].innerHTML =
"[<a href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
}
}
}
},
install: function(toclevels) {
var timerId;
function reinstall() {
asciidoc.footnotes();
if (toclevels) {
asciidoc.toc(toclevels);
}
}
function reinstallAndRemoveTimer() {
clearInterval(timerId);
reinstall();
}
timerId = setInterval(reinstall, 500);
if (document.addEventListener)
document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
else
window.onload = reinstallAndRemoveTimer;
}
}
asciidoc.install();
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>JavaScript I - Variables, Functions, and Scope</h1>
<span id="author">Bruce Harris, 7/31/12</span><br>
</div>
<div id="content">
<div class="sect1">
<h2 id="_content_and_target_audience">Content and Target Audience</h2>
<div class="sectionbody">
<div class="paragraph"><p>Emphasis on behavior/syntax specific to JavaScript (as compared to other languages).</p></div>
<div class="paragraph"><p>JavaScript experience not required, but
you have experience programming in a C style language.</p></div>
<div class="paragraph"><p>Output of code snippet below is obvious to you.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="c1">// document.writeln is a printing function</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s2">&quot;, &quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_resources_and_tools">Resources and Tools</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
These slides: <a href="http://bruceharris.net/techtalks/">http://bruceharris.net/techtalks</a>
</p>
</li>
<li>
<p>
Sandbox: <a href="http://codepen.io/pen">CodePen</a>
</p>
</li>
<li>
<p>
Reference: <a href="https://developer.mozilla.org/en/JavaScript/">Mozilla Developer Network</a>
</p>
</li>
<li>
<p>
Instruction (online book): <a href="http://eloquentjavascript.net/contents.html">Eloquent JavaScript</a>
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_not_as_i_do_8230">Not as I do&#8230;</h2>
<div class="sectionbody">
<div class="paragraph"><p>Avoid <span class="monospaced">document.writeln()</span> - not useful in real life, but useful for examples</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_the_span_class_monospaced_var_span_keyword">The <span class="monospaced">var</span> keyword</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_is_span_class_monospaced_var_span_optional">Is <span class="monospaced">var</span> Optional?</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// hmmmmmm.....</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Above code works, but is <strong>evil</strong>. Assigning variables without declaration using
<span class="monospaced">var</span> creates <em>global</em> variables regardless of where they are declared (this is
usually a very bad thing).</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_the_span_class_monospaced_typeof_span_operator">The <span class="monospaced">typeof</span> operator</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">s</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">s</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_dynamic_typing">Dynamic Typing</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
<span class="nx">x</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span> <span class="c1">// can we change a number to a string?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mf">1.1</span><span class="p">;</span> <span class="c1">// is a decimal different from an integer?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_statement">Function Statement</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">print</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// note no semicolon</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_expression">Function Expression</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="c1">// anonymous function</span>
<span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_functions_as_a_href_http_en_wikipedia_org_wiki_first_class_citizen_first_class_citizens_a">Functions as <a href="http://en.wikipedia.org/wiki/First-class_citizen">First Class Citizens</a></h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="c1">// capture function in variable</span>
<span class="kd">var</span> <span class="nx">print</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_passing_a_function_as_an_argument_to_another_function">Passing a Function as an Argument to Another Function</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">print</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">italic</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="s1">&#39;&lt;em&gt;&#39;</span> <span class="o">+</span> <span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;/em&gt;&#39;</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">callFunc</span><span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">arg</span><span class="p">){</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">callFunc</span><span class="p">(</span><span class="nx">print</span><span class="p">,</span> <span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="nx">italic</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">));</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_returning_a_function_from_a_function">Returning a function from a function</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">print</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">italic</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="s1">&#39;&lt;em&gt;&#39;</span> <span class="o">+</span> <span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;/em&gt;&#39;</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">makeCompoundFunction</span><span class="p">(</span><span class="nx">outer</span><span class="p">,</span> <span class="nx">inner</span><span class="p">){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">outer</span><span class="p">(</span><span class="nx">inner</span><span class="p">(</span><span class="nx">arg</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">printItalic</span> <span class="o">=</span> <span class="nx">makeCompoundFunction</span><span class="p">(</span><span class="nx">print</span><span class="p">,</span> <span class="nx">italic</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">printItalic</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_block_scope_v_function_scope">Block Scope v. Function Scope</h2>
<div class="sectionbody">
<div class="paragraph"><p>Most C style languages have <em>block</em> scope.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// did we change x or create a new x?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_scope">Function Scope</h2>
<div class="sectionbody">
<div class="paragraph"><p>JavaScript <em>does not have block scope</em>, it has only <em>function scope</em></p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// did we change x or create a new x?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_lexical_scoping_v_dynamic_scoping">Lexical Scoping v. Dynamic Scoping</h2>
<div class="sectionbody">
<div class="paragraph"><p>Most C style languages have
<a href="http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping">Lexical Scoping</a>.
So does JavaScript.</p></div>
<div class="ulist incremental"><ul>
<li>
<p>
Every function creates its own scope environment
</p>
</li>
<li>
<p>
Variables declared inside a function are&#8230;
</p>
<div class="ulist"><ul>
<li>
<p>
visible everywhere inside that function
</p>
</li>
<li>
<p>
not visible outside that function
</p>
</li>
</ul></div>
</li>
<li>
<p>
Variables (or functions) declared outside of any function are <em>global</em>
</p>
</li>
</ul></div>
<div class="paragraph incremental"><p>More specifically&#8230;</p></div>
<div class="ulist incremental"><ul>
<li>
<p>
In JavaScript functions can be nested inside other functions
</p>
</li>
<li>
<p>
A function has access to the scope environment of its parent function(s)
</p>
</li>
<li>
<p>
Thus, variables declared inside a function are visible inside functions nested inside the same function
</p>
</li>
</ul></div>
<div class="paragraph incremental"><p>Closure</p></div>
<div class="ulist incremental"><ul>
<li>
<p>
Scope environment created by a function can persist even after function finishes executing
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_declare_x_in_global_scope">Declare x in global scope</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_declare_x_in_function_scope">Declare x in function scope</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span> <span class="c1">// will this work?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_declare_x_in_global_scope_and_in_function_scope">Declare x in global scope and in function scope</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_declare_x_in_global_scope_and_as_function_parameter">Declare x in global scope and as function parameter</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_reference_x_in_function_scope_without_span_class_monospaced_var_span_keyword">Reference x in function scope without <span class="monospaced">var</span> keyword</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// is this a good idea?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span> <span class="c1">// will this work?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_declare_nested_function_and_call_it_outside">Declare nested function and call it outside</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f1</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f2</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">f2</span><span class="p">();</span> <span class="c1">// will this work?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_declare_nested_function_and_call_it_inside">Declare nested function and call it inside</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f1</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f2</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f2</span><span class="p">();</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f1</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_closure">Closure</h2>
<div class="sectionbody">
<div class="paragraph"><p>Environment created by invoking a function persists even after
function is finished executing.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeAccumulator</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">x</span> <span class="o">+=</span> <span class="nx">n</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">x</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">accum</span> <span class="o">=</span> <span class="nx">makeAccumulator</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum</span><span class="p">(</span><span class="mi">13</span><span class="p">));</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_closure_creates_a_new_persistent_environment">Closure creates a new persistent environment</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeAccumulator</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">x</span> <span class="o">+=</span> <span class="nx">n</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">x</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">accum1</span> <span class="o">=</span> <span class="nx">makeAccumulator</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum1</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum1</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span>
<span class="kd">var</span> <span class="nx">accum2</span> <span class="o">=</span> <span class="nx">makeAccumulator</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum2</span><span class="p">(</span><span class="mi">23</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum2</span><span class="p">(</span><span class="mi">17</span><span class="p">));</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_hoisting">Function Hoisting</h2>
<div class="sectionbody">
<div class="paragraph"><p><strong>Most important difference</strong> between function statements and function expressions:</p></div>
<div class="paragraph"><p>Function statements are "hoisted" to the top of the scope in
which they appear. Regardless of where they appear within a scope environment,
it is as if they were declared at the top of that scope environment.</p></div>
<div class="paragraph"><p>Function expressions are <em>not</em> hoisted.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">f1</span><span class="p">;</span>
<span class="nx">f1</span><span class="p">();</span> <span class="c1">// can we call f1 before function expression assignment?</span>
<span class="nx">f1</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">f2</span><span class="p">();</span> <span class="c1">// can we call f2 before its declaration via function statement?</span>
<span class="kd">function</span> <span class="nx">f2</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_function_expressions_are_em_not_em_hoisted">Function expressions are <em>not</em> hoisted</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">f</span><span class="p">;</span>
<span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">2</span><span class="p">;</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span>
<span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_hoisting_can_cause_unintuitive_behavior">Hoisting can cause unintuitive behavior</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">f</span><span class="p">;</span>
<span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span> <span class="k">return</span> <span class="mi">2</span><span class="p">;</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span> <span class="k">return</span> <span class="mi">1</span> <span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span> <span class="c1">// did we re-assign f?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_immediate_function">Immediate function</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="s2">&quot;cool, no global variables!&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>
<span class="p">})();</span> <span class="c1">// anonymous function invoked immediately</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_1">Exercise 1</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeAdder</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">add7</span> <span class="o">=</span> <span class="nx">makeAdder</span><span class="p">(</span><span class="mi">7</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add7</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span> <span class="c1">// 11</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add7</span><span class="p">(</span><span class="mi">9</span><span class="p">));</span> <span class="c1">// 16</span>
<span class="kd">var</span> <span class="nx">add3</span> <span class="o">=</span> <span class="nx">makeAdder</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add3</span><span class="p">(</span><span class="mi">6</span><span class="p">));</span> <span class="c1">// 9</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add3</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="c1">// 5</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_2">Exercise 2</h2>
<div class="sectionbody">
<div class="paragraph"><p>Not practical, but a good exercise in functional programming</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">sum1</span> <span class="o">=</span> <span class="p">(</span>
<span class="c1">// your code here</span>
<span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">sum1</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)());</span> <span class="c1">// 7</span>
<span class="kd">var</span> <span class="nx">sum2</span> <span class="o">=</span> <span class="p">(</span>
<span class="c1">// your code here</span>
<span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">sum2</span><span class="p">()(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">));</span> <span class="c1">// 7</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_3">Exercise 3</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCounter</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">increment</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">counter1</span> <span class="o">=</span> <span class="nx">makeCounter</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter1</span><span class="p">());</span> <span class="c1">// 100</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter1</span><span class="p">());</span> <span class="c1">// 101</span>
<span class="kd">var</span> <span class="nx">counter2</span> <span class="o">=</span> <span class="nx">makeCounter</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter2</span><span class="p">());</span> <span class="c1">// 10</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter2</span><span class="p">());</span> <span class="c1">// 15</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_4">Exercise 4</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">add</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">+</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">subtract</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">-</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// operation is either &#39;+&#39; or &#39;-&#39;</span>
<span class="kd">function</span> <span class="nx">makeReducer</span><span class="p">(</span><span class="nx">operation</span><span class="p">){</span>
<span class="c1">// your code here, preferably just one line</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">plus</span> <span class="o">=</span> <span class="nx">makeReducer</span><span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">plus</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">));</span> <span class="c1">// 9</span>
<span class="kd">var</span> <span class="nx">minus</span> <span class="o">=</span> <span class="nx">makeReducer</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">minus</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">));</span> <span class="c1">// -1</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1">
<h2 id="_exercise_5">Exercise 5</h2>
<div class="sectionbody">
<div class="paragraph"><p>Modify solution to Exercise 4 to remove <span class="monospaced">add</span> and <span class="monospaced">subtract</span> from the global scope</p></div>
</div>
</div>
</div>
<div id="footnotes"><hr></div>
<div id="footer">
<div id="footer-text">
Last updated 2012-07-31 13:09:11 Eastern Daylight Time
</div>
</div>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>JavaScript I - Variables, Functions, and Scope</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="copyright" content="Copyright &#169; Bruce Harris, 7/31/12" />
<meta name="generator" content="AsciiDoc 8.6.7" />
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
pre {
padding: 0;
margin: 0;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
tt {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
.monospaced {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
}
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/* slidy.css
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
/*
SJR: 2010-09-29: Modified for AsciiDoc slidy backend.
Mostly just commented out stuff that is handled by AsciiDoc's CSS files.
*/
body
{
margin: 0 0 0 0;
padding: 0 0 0 0;
width: 100%;
height: 100%;
color: black;
background-color: white;
/*
font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
*/
font-size: 14pt;
}
div.toolbar {
position: fixed; z-index: 200;
top: auto; bottom: 0; left: 0; right: 0;
height: 1.2em; text-align: right;
padding-left: 1em;
padding-right: 1em;
font-size: 60%;
color: red;
background-color: rgb(240,240,240);
border-top: solid 1px rgb(180,180,180);
}
div.toolbar span.copyright {
color: black;
margin-left: 0.5em;
}
div.initial_prompt {
position: absolute;
z-index: 1000;
bottom: 1.2em;
width: 90%;
background-color: rgb(200,200,200);
opacity: 0.35;
background-color: rgb(200,200,200, 0.35);
cursor: pointer;
}
div.initial_prompt p.help {
text-align: center;
}
div.initial_prompt p.close {
text-align: right;
font-style: italic;
}
div.slidy_toc {
position: absolute;
z-index: 300;
width: 60%;
max-width: 30em;
height: 30em;
overflow: auto;
top: auto;
right: auto;
left: 4em;
bottom: 4em;
padding: 1em;
background: rgb(240,240,240);
border-style: solid;
border-width: 2px;
font-size: 60%;
}
div.slidy_toc .toc_heading {
text-align: center;
width: 100%;
margin: 0;
margin-bottom: 1em;
border-bottom-style: solid;
border-bottom-color: rgb(180,180,180);
border-bottom-width: 1px;
}
div.slide {
z-index: 20;
margin: 0 0 0 0;
padding-top: 0;
padding-bottom: 0;
padding-left: 20px;
padding-right: 20px;
border-width: 0;
clear: both;
top: 0;
bottom: 0;
left: 0;
right: 0;
line-height: 120%;
background-color: transparent;
}
div.background {
display: none;
}
div.handout {
margin-left: 20px;
margin-right: 20px;
}
div.slide.titlepage {
text-align: center;
}
div.slide.titlepage.h1 {
padding-top: 10%;
}
div.slide h1 {
padding-left: 0;
padding-right: 20pt;
padding-top: 4pt;
padding-bottom: 4pt;
margin-top: 0;
margin-left: 0;
margin-right: 60pt;
margin-bottom: 0.5em;
display: block;
font-size: 160%;
line-height: 1.2em;
background: transparent;
}
div.toc {
position: absolute;
top: auto;
bottom: 4em;
left: 4em;
right: auto;
width: 60%;
max-width: 30em;
height: 30em;
border: solid thin black;
padding: 1em;
background: rgb(240,240,240);
color: black;
z-index: 300;
overflow: auto;
display: block;
visibility: visible;
}
div.toc-heading {
width: 100%;
border-bottom: solid 1px rgb(180,180,180);
margin-bottom: 1em;
text-align: center;
}
/*
pre {
font-size: 80%;
font-weight: bold;
line-height: 120%;
padding-top: 0.2em;
padding-bottom: 0.2em;
padding-left: 1em;
padding-right: 1em;
border-style: solid;
border-left-width: 1em;
border-top-width: thin;
border-right-width: thin;
border-bottom-width: thin;
border-color: #95ABD0;
color: #00428C;
background-color: #E4E5E7;
}
*/
/*
li pre { margin-left: 0; }
blockquote { font-style: italic }
img { background-color: transparent }
p.copyright { font-size: smaller }
*/
.center { text-align: center }
.footnote { font-size: smaller; margin-left: 2em; }
/*
a img { border-width: 0; border-style: none }
*/
a:visited { color: navy }
a:link { color: navy }
a:hover { color: red; text-decoration: underline }
a:active { color: red; text-decoration: underline }
a {text-decoration: none}
.navbar a:link {color: white}
.navbar a:visited {color: yellow}
.navbar a:active {color: red}
.navbar a:hover {color: red}
/*
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
li { margin-left: 0.5em; margin-top: 0.5em; }
li li { font-size: 85%; font-style: italic }
li li li { font-size: 85%; font-style: normal }
*/
div dt
{
margin-left: 0;
margin-top: 1em;
margin-bottom: 0.5em;
font-weight: bold;
}
div dd
{
margin-left: 2em;
margin-bottom: 0.5em;
}
/*
p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
margin-left: 1em;
margin-right: 1em;
}
*/
p.subhead { font-weight: bold; margin-top: 2em; }
.smaller { font-size: smaller }
.bigger { font-size: 130% }
/*
td,th { padding: 0.2em }
*/
ul {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ol {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
/*
ul li {
list-style: square;
margin: 0.1em 0em 0.6em 0;
padding: 0 0 0 0;
line-height: 140%;
}
ol li {
margin: 0.1em 0em 0.6em 1.5em;
padding: 0 0 0 0px;
line-height: 140%;
list-style-type: decimal;
}
li ul li {
font-size: 85%;
font-style: italic;
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li li ul li {
font-size: 85%;
font-style: normal;
list-style-type: circle;
background: transparent;
padding: 0 0 0 0;
}
li li li ul li {
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li ol li {
list-style-type: decimal;
}
li li ol li {
list-style-type: decimal;
}
*/
/*
setting class="outline" on ol or ul makes it behave as an
ouline list where blocklevel content in li elements is
hidden by default and can be expanded or collapsed with
mouse click. Set class="expand" on li to override default
*/
ol.outline li:hover { cursor: pointer }
ol.outline li.nofold:hover { cursor: default }
ul.outline li:hover { cursor: pointer }
ul.outline li.nofold:hover { cursor: default }
ol.outline { list-style:decimal; }
ol.outline ol { list-style-type:lower-alpha }
ol.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
ul.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
/* for slides with class "title" in table of contents */
a.titleslide { font-weight: bold; font-style: italic }
/*
hide images for work around for save as bug
where browsers fail to save images used by CSS
*/
img.hidden { display: none; visibility: hidden }
div.initial_prompt { display: none; visibility: hidden }
div.slide {
visibility: visible;
position: inherit;
}
div.handout {
border-top-style: solid;
border-top-width: thin;
border-top-color: black;
}
@media screen {
.hidden { display: none; visibility: visible }
div.slide.hidden { display: block; visibility: visible }
div.handout.hidden { display: block; visibility: visible }
div.background { display: none; visibility: hidden }
body.single_slide div.initial_prompt { display: block; visibility: visible }
body.single_slide div.background { display: block; visibility: visible }
body.single_slide div.background.hidden { display: none; visibility: hidden }
body.single_slide .invisible { visibility: hidden }
body.single_slide .hidden { display: none; visibility: hidden }
body.single_slide div.slide { position: absolute }
body.single_slide div.handout { display: none; visibility: hidden }
}
@media print {
.hidden { display: block; visibility: visible }
/*
div.slide pre { font-size: 60%; padding-left: 0.5em; }
*/
div.toolbar { display: none; visibility: hidden; }
div.slidy_toc { display: none; visibility: hidden; }
div.background { display: none; visibility: hidden; }
div.slide { page-break-before: always }
/* :first-child isn't reliable for print media */
div.slide.first-slide { page-break-before: avoid }
}
/* SJR: AsciiDoc slidy backend tweaks */
ol, ul {
margin: 0.8em 1.5em 0.8em 1.8em;
}
li > ul, li > ol {
margin-top: 0.5em;
}
.outline > li.folded,
.outline > li.unfolded {
color: #527bbd;
}
ul > li{ color: #aaa; }
ul > li > *, ol > li > * { color: black; }
li {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
/*
pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
<script type="text/javascript">
/*<![CDATA[*/
/* slidy.js
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
// the slidy object implementation
var w3c_slidy = {
// classify which kind of browser we're running under
ns_pos: (typeof window.pageYOffset!='undefined'),
khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false),
opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false),
ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false),
iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false),
ie: (typeof document.all != "undefined" && !this.opera),
ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1),
ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1),
ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1),
ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1),
keyboardless: (this.ipad || this.iphone),
// are we running as XHTML? (doesn't work on Opera)
is_xhtml: /xml/.test(document.contentType),
slide_number: 0, // integer slide count: 0, 1, 2, ...
slide_number_element: null, // element containing slide number
slides: [], // set to array of slide div's
notes: [], // set to array of handout div's
backgrounds: [], // set to array of background div's
toolbar: null, // element containing toolbar
title: null, // document title
last_shown: null, // last incrementally shown item
eos: null, // span element for end of slide indicator
toc: null, // table of contents
outline: null, // outline element with the focus
selected_text_len: 0, // length of drag selection on document
view_all: 0, // 1 to view all slides + handouts
want_toolbar: true, // user preference to show/hide toolbar
mouse_click_enabled: true, // enables left click for next slide
scroll_hack: 0, // IE work around for position: fixed
disable_slide_click: false, // used by clicked anchors
lang: "en", // updated to language specified by html file
help_anchor: null, // used for keyboard focus hack in showToolbar()
help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html",
help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " +
"or Pg Up and Pg Dn. Use S and B to change font size.",
size_index: 0,
size_adjustment: 0,
sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
"22pt", "24pt", "26pt", "28pt", "30pt", "32pt"),
// needed for efficient resizing
last_width: 0,
last_height: 0,
// Needed for cross browser support for relative width/height on
// object elements. The work around is to save width/height attributes
// and then to recompute absolute width/height dimensions on resizing
objects: [],
// attach initialiation event handlers
set_up: function () {
var init = function() { w3c_slidy.init(); };
if (typeof window.addEventListener != "undefined")
window.addEventListener("load", init, false);
else
window.attachEvent("onload", init);
},
hide_slides: function () {
if (document.body && !w3c_slidy.initialized)
document.body.style.visibility = "hidden";
else
setTimeout(w3c_slidy.hide_slides, 50);
},
// hack to persuade IE to compute correct document height
// as needed for simulating fixed positioning of toolbar
ie_hack: function () {
window.resizeBy(0,-1);
window.resizeBy(0, 1);
},
init: function () {
//alert("slidy starting test 10");
document.body.style.visibility = "visible";
w3c_slidy_i18n.init();
this.add_toolbar();
this.wrap_implicit_slides();
this.collect_slides();
this.collect_notes();
this.collect_backgrounds();
this.objects = document.body.getElementsByTagName("object");
this.patch_anchors();
this.slide_number = this.find_slide_number(location.href);
window.offscreenbuffering = true;
this.size_adjustment = this.find_size_adjust();
this.time_left = this.find_duration();
this.hide_image_toolbar(); // suppress IE image toolbar popup
this.init_outliner(); // activate fold/unfold support
this.title = document.title;
// work around for opera bug
this.is_xhtml = (document.body.tagName == "BODY" ? false : true);
if (this.slides.length > 0)
{
var slide = this.slides[this.slide_number];
if (this.slide_number > 0)
{
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
this.set_eos_status(true);
}
else
{
this.last_shown = null;
this.set_visibility_all_incremental("hidden");
this.set_eos_status(!this.next_incremental_item(this.last_shown));
}
this.set_location();
this.add_class(this.slides[0], "first-slide");
w3c_slidy.show_slide(slide);
}
this.toc = this.table_of_contents();
this.add_initial_prompt();
// bind event handlers without interfering with custom page scripts
// Tap events behave too weirdly to support clicks reliably on
// iPhone and iPad, so exclude these from click handler
if (!this.keyboardless)
this.add_listener(document.body, "click", this.mouse_button_click);
this.add_listener(document, "keydown", this.key_down);
this.add_listener(document, "keypress", this.key_press);
this.add_listener(window, "resize", this.resized);
this.add_listener(window, "scroll", this.scrolled);
this.add_listener(window, "unload", this.unloaded);
if (!document.body.onclick)
document.body.onclick = function () { };
this.single_slide_view();
//this.set_location();
this.resized();
if (this.ie7)
setTimeout(w3c_slidy.ie_hack, 100);
this.show_toolbar();
// for back button detection
setInterval(function () { w3c_slidy.check_location(); }, 200);
w3c_slidy.initialized = true;
},
// create div element with links to each slide
table_of_contents: function () {
var toc = this.create_element("div");
this.add_class(toc, "slidy_toc hidden");
//toc.setAttribute("tabindex", "0");
var heading = this.create_element("div");
this.add_class(heading, "toc-heading");
heading.innerHTML = "Table of Contents".localize();
toc.appendChild(heading);
var previous = null;
for (var i = 0; i < this.slides.length; ++i)
{
var title = this.has_class(this.slides[i], "title");
var num = document.createTextNode((i + 1) + ". ");
toc.appendChild(num);
var a = this.create_element("a");
a.setAttribute("href", "#(" + (i+1) + ")");
if (title)
this.add_class(a, "titleslide");
var name = document.createTextNode(this.slide_name(i));
a.appendChild(name);
a.onclick = w3c_slidy.toc_click;
a.onkeydown = w3c_slidy.toc_keydown;
a.previous = previous;
if (previous)
previous.next = a;
toc.appendChild(a);
if (i == 0)
toc.first = a;
if (i < this.slides.length - 1)
{
var br = this.create_element("br");
toc.appendChild(br);
}
previous = a;
}
toc.focus = function () {
if (this.first)
this.first.focus();
}
toc.onmouseup = w3c_slidy.mouse_button_up;
toc.onclick = function (e) {
e||(e=window.event);
if (w3c_slidy.selected_text_len <= 0)
w3c_slidy.hide_table_of_contents();
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
};
document.body.insertBefore(toc, document.body.firstChild);
return toc;
},
is_shown_toc: function () {
return !w3c_slidy.has_class(w3c_slidy.toc, "hidden");
},
show_table_of_contents: function () {
w3c_slidy.remove_class(w3c_slidy.toc, "hidden");
var toc = w3c_slidy.toc;
toc.focus();
if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0)
setTimeout(w3c_slidy.ie_hack, 100);
},
hide_table_of_contents: function () {
w3c_slidy.add_class(w3c_slidy.toc, "hidden");
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
},
toggle_table_of_contents: function () {
if (w3c_slidy.is_shown_toc())
w3c_slidy.hide_table_of_contents();
else
w3c_slidy.show_table_of_contents();
},
// called on clicking toc entry
toc_click: function (e) {
if (!e)
e = window.event;
var target = w3c_slidy.get_target(e);
if (target && target.nodeType == 1)
{
var uri = target.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
}
w3c_slidy.hide_table_of_contents(e);
if (w3c_slidy.ie7) w3c_slidy.ie_hack();
w3c_slidy.stop_propagation(e);
return w3c_slidy.cancel(e);
},
// called onkeydown for toc entry
toc_keydown: function (event) {
var key;
if (!event)
var event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey)
return true;
if (key == 13)
{
var uri = this.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
w3c_slidy.hide_table_of_contents();
if (self.ie7)
w3c_slidy.ie_hack();
return w3c_slidy.cancel(event);
}
if (key == 40 && this.next)
{
this.next.focus();
return w3c_slidy.cancel(event);
}
if (key == 38 && this.previous)
{
this.previous.focus();
return w3c_slidy.cancel(event);
}
return true;
},
// ### OBSOLETE ###
before_print: function () {
this.show_all_slides();
this.hide_toolbar();
alert("before print");
},
// ### OBSOLETE ###
after_print: function () {
if (!this.view_all)
{
this.single_slide_view();
this.show_toolbar();
}
alert("after print");
},
// ### OBSOLETE ###
print_slides: function () {
this.before_print();
window.print();
this.after_print();
},
// ### OBSOLETE ?? ###
toggle_view: function () {
if (this.view_all)
{
this.single_slide_view();
this.show_toolbar();
this.view_all = 0;
}
else
{
this.show_all_slides();
this.hide_toolbar();
this.view_all = 1;
}
},
// prepare for printing ### OBSOLETE ###
show_all_slides: function () {
this.remove_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
},
// restore after printing ### OBSOLETE ###
single_slide_view: function () {
this.add_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
},
// suppress IE's image toolbar pop up
hide_image_toolbar: function () {
if (!this.ns_pos)
{
var images = document.getElementsByTagName("IMG");
for (var i = 0; i < images.length; ++i)
images[i].setAttribute("galleryimg", "no");
}
},
unloaded: function (e) {
//alert("unloaded");
},
// Safari and Konqueror don't yet support getComputedStyle()
// and they always reload page when location.href is updated
is_KHTML: function () {
var agent = navigator.userAgent;
return (agent.indexOf("KHTML") >= 0 ? true : false);
},
// find slide name from first h1 element
// default to document title + slide number
slide_name: function (index) {
var name = null;
var slide = this.slides[index];
var heading = this.find_heading(slide);
if (heading)
name = this.extract_text(heading);
if (!name)
name = this.title + "(" + (index + 1) + ")";
name.replace(/\&/g, "&amp;");
name.replace(/\</g, "&lt;");
name.replace(/\>/g, "&gt;");
return name;
},
// find first h1 element in DOM tree
find_heading: function (node) {
if (!node || node.nodeType != 1)
return null;
if (node.nodeName == "H1" || node.nodeName == "h1")
return node;
var child = node.firstChild;
while (child)
{
node = this.find_heading(child);
if (node)
return node;
child = child.nextSibling;
}
return null;
},
// recursively extract text from DOM tree
extract_text: function (node) {
if (!node)
return "";
// text nodes
if (node.nodeType == 3)
return node.nodeValue;
// elements
if (node.nodeType == 1)
{
node = node.firstChild;
var text = "";
while (node)
{
text = text + this.extract_text(node);
node = node.nextSibling;
}
return text;
}
return "";
},
// find copyright text from meta element
find_copyright: function () {
var name, content;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "copyright")
return content;
}
return null;
},
find_size_adjust: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "font-size-adjustment")
return 1 * content;
}
return 1;
},
// <meta name="duration" content="20" /> for 20 minutes
find_duration: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "duration")
return 60000 * content;
}
return null;
},
replace_by_non_breaking_space: function (str) {
for (var i = 0; i < str.length; ++i)
str[i] = 160;
},
// ### CHECK ME ### is use of "li" okay for text/html?
// for XHTML do we also need to specify namespace?
init_outliner: function () {
var items = document.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i)
{
var target = items[i];
if (!this.has_class(target.parentNode, "outline"))
continue;
target.onclick = this.outline_click;
/* ### more work needed for IE6
if (!this.ns_pos)
{
target.onmouseover = this.hover_outline;
target.onmouseout = this.unhover_outline;
}
*/
if (this.foldable(target))
{
target.foldable = true;
target.onfocus = function () {w3c_slidy.outline = this;};
target.onblur = function () {w3c_slidy.outline = null;};
if (!target.getAttribute("tabindex"))
target.setAttribute("tabindex", "0");
if (this.has_class(target, "expand"))
this.unfold(target);
else
this.fold(target);
}
else
{
this.add_class(target, "nofold");
target.visible = true;
target.foldable = false;
}
}
},
foldable: function (item) {
if (!item || item.nodeType != 1)
return false;
var node = item.firstChild;
while (node)
{
if (node.nodeType == 1 && this.is_block(node))
return true;
node = node.nextSibling;
}
return false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
fold: function (item) {
if (item)
{
this.remove_class(item, "unfolded");
this.add_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.add_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
unfold: function (item) {
if (item)
{
this.add_class(item, "unfolded");
this.remove_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.remove_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = true;
},
outline_click: function (e) {
if (!e)
e = window.event;
var rightclick = false;
var target = w3c_slidy.get_target(e);
while (target && target.visible == undefined)
target = target.parentNode;
if (!target)
return true;
if (e.which)
rightclick = (e.which == 3);
else if (e.button)
rightclick = (e.button == 2);
if (!rightclick && target.visible != undefined)
{
if (target.foldable)
{
if (target.visible)
w3c_slidy.fold(target);
else
w3c_slidy.unfold(target);
}
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
}
return false;
},
add_initial_prompt: function () {
var prompt = this.create_element("div");
prompt.setAttribute("class", "initial_prompt");
var p1 = this.create_element("p");
prompt.appendChild(p1);
p1.setAttribute("class", "help");
if (this.keyboardless)
p1.innerHTML = "Tap footer to move to next slide";
else
p1.innerHTML = "Space or Right Arrow to move to next " +
"slide, click help below for more details";
this.add_listener(prompt, "click", function (e) {
document.body.removeChild(prompt);
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
});
document.body.appendChild(prompt);
this.initial_prompt = prompt;
setTimeout(function() {document.body.removeChild(prompt);}, 5000);
},
add_toolbar: function () {
var counter, page;
this.toolbar = this.create_element("div");
this.toolbar.setAttribute("class", "toolbar");
// a reasonably behaved browser
if (this.ns_pos || !this.ie6)
{
var right = this.create_element("div");
right.setAttribute("style", "float: right; text-align: right");
counter = this.create_element("span")
counter.innerHTML = "slide".localize() + " n/m";
right.appendChild(counter);
this.toolbar.appendChild(right);
var left = this.create_element("div");
left.setAttribute("style", "text-align: left");
// global end of slide indicator
this.eos = this.create_element("span");
this.eos.innerHTML = "* ";
left.appendChild(this.eos);
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
left.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
left.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
left.appendChild(contents);
var gap2 = document.createTextNode(" ");
left.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.className = "copyright";
span.innerHTML = copyright;
left.appendChild(span);
}
this.toolbar.setAttribute("tabindex", "0");
this.toolbar.appendChild(left);
}
else // IE6 so need to work around its poor CSS support
{
this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute");
this.toolbar.style.zIndex = "200";
this.toolbar.style.width = "99.9%";
this.toolbar.style.height = "1.2em";
this.toolbar.style.top = "auto";
this.toolbar.style.bottom = "0";
this.toolbar.style.left = "0";
this.toolbar.style.right = "0";
this.toolbar.style.textAlign = "left";
this.toolbar.style.fontSize = "60%";
this.toolbar.style.color = "red";
this.toolbar.borderWidth = 0;
this.toolbar.className = "toolbar";
this.toolbar.style.background = "rgb(240,240,240)";
// would like to have help text left aligned
// and page counter right aligned, floating
// div's don't work, so instead use nested
// absolutely positioned div's.
var sp = this.create_element("span");
sp.innerHTML = "&nbsp;&nbsp;*&nbsp;";
this.toolbar.appendChild(sp);
this.eos = sp; // end of slide indicator
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
this.toolbar.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
this.toolbar.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:toggleTableOfContents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
this.toolbar.appendChild(contents);
var gap2 = document.createTextNode(" ");
this.toolbar.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.innerHTML = copyright;
span.style.color = "black";
span.style.marginLeft = "0.5em";
this.toolbar.appendChild(span);
}
counter = this.create_element("div")
counter.style.position = "absolute";
counter.style.width = "auto"; //"20%";
counter.style.height = "1.2em";
counter.style.top = "auto";
counter.style.bottom = 0;
counter.style.right = "0";
counter.style.textAlign = "right";
counter.style.color = "red";
counter.style.background = "rgb(240,240,240)";
counter.innerHTML = "slide".localize() + " n/m";
this.toolbar.appendChild(counter);
}
// ensure that click isn't passed through to the page
this.toolbar.onclick =
function (e) {
if (!e)
e = window.event;
var target = e.target;
if (!target && e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target && target.nodeType == 3)
target = target.parentNode;
w3c_slidy.stop_propagation(e);
if (target && target.nodeName.toLowerCase() != "a")
w3c_slidy.mouse_button_click(e);
};
this.slide_number_element = counter;
this.set_eos_status(false);
document.body.appendChild(this.toolbar);
},
// wysiwyg editors make it hard to use div elements
// e.g. amaya loses the div when you copy and paste
// this function wraps div elements around implicit
// slides which start with an h1 element and continue
// up to the next heading or div element
wrap_implicit_slides: function () {
var i, heading, node, next, div;
var headings = document.getElementsByTagName("h1");
if (!headings)
return;
for (i = 0; i < headings.length; ++i)
{
heading = headings[i];
if (heading.parentNode != document.body)
continue;
node = heading.nextSibling;
div = document.createElement("div");
this.add_class(div, "slide");
document.body.replaceChild(div, heading);
div.appendChild(heading);
while (node)
{
if (node.nodeType == 1 && // an element
(node.nodeName == "H1" ||
node.nodeName == "h1" ||
node.nodeName == "DIV" ||
node.nodeName == "div"))
break;
next = node.nextSibling;
node = document.body.removeChild(node);
div.appendChild(node);
node = next;
}
}
},
// return new array of all slides
collect_slides: function () {
var slides = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "slide"))
{
// add slide to collection
slides[slides.length] = div;
// hide each slide as it is found
this.add_class(div, "hidden");
// add dummy <br/> at end for scrolling hack
var node1 = document.createElement("br");
div.appendChild(node1);
var node2 = document.createElement("br");
div.appendChild(node2);
}
else if (this.has_class(div, "background"))
{ // work around for Firefox SVG reload bug
// which otherwise replaces 1st SVG graphic with 2nd
div.style.display = "block";
}
}
this.slides = slides;
},
// return new array of all <div class="handout">
collect_notes: function () {
var notes = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "handout"))
{
// add note to collection
notes[notes.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.notes = notes;
},
// return new array of all <div class="background">
// including named backgrounds e.g. class="background titlepage"
collect_backgrounds: function () {
var backgrounds = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "background"))
{
// add background to collection
backgrounds[backgrounds.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.backgrounds = backgrounds;
},
// set click handlers on all anchors
patch_anchors: function () {
var self = w3c_slidy;
var handler = function (event) {
// compare this.href with location.href
// for link to another slide in this doc
if (self.page_address(this.href) == self.page_address(location.href))
{
// yes, so find new slide number
var newslidenum = self.find_slide_number(this.href);
if (newslidenum != self.slide_number)
{
var slide = self.slides[self.slide_number];
self.hide_slide(slide);
self.slide_number = newslidenum;
slide = self.slides[self.slide_number];
self.show_slide(slide);
self.set_location();
}
}
else if (this.target == null)
location.href = this.href;
this.blur();
self.disable_slide_click = true;
};
var anchors = document.body.getElementsByTagName("a");
for (var i = 0; i < anchors.length; ++i)
{
if (window.addEventListener)
anchors[i].addEventListener("click", handler, false);
else
anchors[i].attachEvent("onclick", handler);
}
},
// ### CHECK ME ### see which functions are invoked via setTimeout
// either directly or indirectly for use of w3c_slidy vs this
show_slide_number: function () {
var timer = w3c_slidy.get_timer();
w3c_slidy.slide_number_element.innerHTML = timer + "slide".localize() + " " +
(w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length;
},
// every 200mS check if the location has been changed as a
// result of the user activating the Back button/menu item
// doesn't work for Opera < 9.5
check_location: function () {
var hash = location.hash;
if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#"))
w3c_slidy.goto_slide(0);
else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")")
{
var num = parseInt(location.hash.substr(2));
if (!isNaN(num))
w3c_slidy.goto_slide(num-1);
}
if (w3c_slidy.time_left && w3c_slidy.slide_number > 0)
{
w3c_slidy.show_slide_number();
if (w3c_slidy.time_left > 0)
w3c_slidy.time_left -= 200;
}
},
get_timer: function () {
var timer = "";
if (w3c_slidy.time_left)
{
var mins, secs;
secs = Math.floor(w3c_slidy.time_left/1000);
mins = Math.floor(secs / 60);
secs = secs % 60;
timer = (mins ? mins+"m" : "") + secs + "s ";
}
return timer;
},
// this doesn't push location onto history stack for IE
// for which a hidden iframe hack is needed: load page into
// the iframe with script that set's parent's location.hash
// but that won't work for standalone use unless we can
// create the page dynamically via a javascript: URL
set_location: function () {
var uri = w3c_slidy.page_address(location.href);
var hash = "#(" + (w3c_slidy.slide_number+1) + ")";
if (w3c_slidy.slide_number >= 0)
uri = uri + hash;
if (w3c_slidy.ie && !w3c_slidy.ie8)
w3c_slidy.push_hash(hash);
if (uri != location.href) // && !khtml
location.href = uri;
if (this.khtml)
hash = "(" + (w3c_slidy.slide_number+1) + ")";
if (!this.ie && location.hash != hash && location.hash != "")
location.hash = hash;
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide_number();
},
page_address: function (uri) {
var i = uri.indexOf("#");
if (i < 0)
i = uri.indexOf("%23");
// check if anchor is entire page
if (i < 0)
return uri; // yes
return uri.substr(0, i);
},
// only used for IE6 and IE7
on_frame_loaded: function (hash) {
location.hash = hash;
var uri = w3c_slidy.page_address(location.href);
location.href = uri + hash;
},
// history hack with thanks to Bertrand Le Roy
push_hash: function (hash) {
if (hash == "") hash = "#(1)";
window.location.hash = hash;
var doc = document.getElementById("historyFrame").contentWindow.document;
doc.open("javascript:'<html></html>'");
// PWL modified this string literal to break the close script tag
// which otherwise gets parsed when incorporated
doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+
(hash) + "');</" + "script></head><body>hello mum</body></html>");
doc.close();
},
// find current slide based upon location
// first find target anchor and then look
// for associated div element enclosing it
// finally map that to slide number
find_slide_number: function (uri) {
// first get anchor from page location
var i = uri.indexOf("#");
// check if anchor is entire page
if (i < 0)
return 0; // yes
var anchor = unescape(uri.substr(i+1));
// now use anchor as XML ID to find target
var target = document.getElementById(anchor);
if (!target)
{
// does anchor look like "(2)" for slide 2 ??
// where first slide is (1)
var re = /\((\d)+\)/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// accept [2] for backwards compatibility
re = /\[(\d)+\]/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// oh dear unknown anchor
return 0;
}
// search for enclosing slide
while (true)
{
// browser coerces html elements to uppercase!
if (target.nodeName.toLowerCase() == "div" &&
this.has_class(target, "slide"))
{
// found the slide element
break;
}
// otherwise try parent element if any
target = target.parentNode;
if (!target)
{
return 0; // no luck!
}
};
for (i = 0; i < slides.length; ++i)
{
if (slides[i] == target)
return i; // success
}
// oh dear still no luck
return 0;
},
previous_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide;
if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null)
{
w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown);
w3c_slidy.set_eos_status(false);
}
else if (w3c_slidy.slide_number > 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.set_eos_status(true);
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_location();
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
next_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide, last = w3c_slidy.last_shown;
if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1)
w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown);
if ((!incremental || w3c_slidy.last_shown == null) &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number + 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
else if (!w3c_slidy.last_shown)
{
if (last && incremental)
w3c_slidy.last_shown = last;
}
w3c_slidy.set_location();
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
// to first slide with nothing revealed
// i.e. state at start of presentation
first_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
if (w3c_slidy.slide_number != 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = 0;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_eos_status(
!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.set_location();
}
},
// goto last slide with everything revealed
// i.e. state at end of presentation
last_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
w3c_slidy.last_shown = null; //revealNextItem(lastShown);
if (w3c_slidy.last_shown == null &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slides.length - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.show_slide(slide);
}
else
{
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
}
w3c_slidy.set_eos_status(true);
w3c_slidy.set_location();
}
},
// ### check this and consider add/remove class
set_eos_status: function (state) {
if (this.eos)
this.eos.style.color = (state ? "rgb(240,240,240)" : "red");
},
// first slide is 0
goto_slide: function (num) {
//alert("going to slide " + (num+1));
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = num;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide(slide);
w3c_slidy.show_slide_number();
},
show_slide: function (slide) {
this.sync_background(slide);
window.scrollTo(0,0);
this.remove_class(slide, "hidden");
},
hide_slide: function (slide) {
this.add_class(slide, "hidden");
},
// show just the backgrounds pertinent to this slide
// when slide background-color is transparent
// this should now work with rgba color values
sync_background: function (slide) {
var background;
var bgColor;
if (slide.currentStyle)
bgColor = slide.currentStyle["backgroundColor"];
else if (document.defaultView)
{
var styles = document.defaultView.getComputedStyle(slide,null);
if (styles)
bgColor = styles.getPropertyValue("background-color");
else // broken implementation probably due Safari or Konqueror
{
//alert("defective implementation of getComputedStyle()");
bgColor = "transparent";
}
}
else
bgColor == "transparent";
if (bgColor == "transparent" ||
bgColor.indexOf("rgba") >= 0 ||
bgColor.indexOf("opacity") >= 0)
{
var slideClass = this.get_class_list(slide);
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
var bgClass = this.get_class_list(background);
if (this.matching_background(slideClass, bgClass))
this.remove_class(background, "hidden");
else
this.add_class(background, "hidden");
}
}
else // forcibly hide all backgrounds
this.hide_backgrounds();
},
hide_backgrounds: function () {
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
this.add_class(background, "hidden");
}
},
// compare classes for slide and background
matching_background: function (slideClass, bgClass) {
var i, count, pattern, result;
// define pattern as regular expression
pattern = /\w+/g;
// check background class names
result = bgClass.match(pattern);
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (result[i] == "background")
continue;
++count;
}
if (count == 0) // default match
return true;
// check for matches and place result in array
result = slideClass.match(pattern);
// now check if desired name is present for background
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (this.has_token(bgClass, result[i]))
return true;
}
return false;
},
resized: function () {
var width = 0;
if ( typeof( window.innerWidth ) == 'number' )
width = window.innerWidth; // Non IE browser
else if (document.documentElement && document.documentElement.clientWidth)
width = document.documentElement.clientWidth; // IE6
else if (document.body && document.body.clientWidth)
width = document.body.clientWidth; // IE4
var height = 0;
if ( typeof( window.innerHeight ) == 'number' )
height = window.innerHeight; // Non IE browser
else if (document.documentElement && document.documentElement.clientHeight)
height = document.documentElement.clientHeight; // IE6
else if (document.body && document.body.clientHeight)
height = document.body.clientHeight; // IE4
if (height && (width/height > 1.05*1024/768))
{
width = height * 1024.0/768;
}
// IE fires onresize even when only font size is changed!
// so we do a check to avoid blocking < and > actions
if (width != w3c_slidy.last_width || height != w3c_slidy.last_height)
{
if (width >= 1100)
w3c_slidy.size_index = 5; // 4
else if (width >= 1000)
w3c_slidy.size_index = 4; // 3
else if (width >= 800)
w3c_slidy.size_index = 3; // 2
else if (width >= 600)
w3c_slidy.size_index = 2; // 1
else if (width)
w3c_slidy.size_index = 0;
// add in font size adjustment from meta element e.g.
// <meta name="font-size-adjustment" content="-2" />
// useful when slides have too much content ;-)
if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment &&
w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length)
w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment;
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
w3c_slidy.adjust_object_dimensions(width, height);
if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index])
{
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
}
w3c_slidy.last_width = width;
w3c_slidy.last_height = height;
// force reflow to work around Mozilla bug
if (w3c_slidy.ns_pos)
{
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
}
// force correct positioning of toolbar
w3c_slidy.refresh_toolbar(200);
}
},
scrolled: function () {
if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset();
// hide toolbar
w3c_slidy.toolbar.style.display = "none";
// make it reappear later
if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all)
{
setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000);
w3c_slidy.scrollhack = 1;
}
}
},
hide_toolbar: function () {
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden");
window.focus();
},
// used to ensure IE refreshes toolbar in correct position
refresh_toolbar: function (interval) {
if (!w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hide_toolbar();
setTimeout(function () {w3c_slidy.show_toolbar(); }, interval);
}
},
// restores toolbar after short delay
show_toolbar: function () {
if (w3c_slidy.want_toolbar)
{
w3c_slidy.toolbar.style.display = "block";
if (!w3c_slidy.ns_pos)
{
// adjust position to allow for scrolling
var xoffset = w3c_slidy.scroll_x_offset();
w3c_slidy.toolbar.style.left = xoffset;
w3c_slidy.toolbar.style.right = xoffset;
// determine vertical scroll offset
//var yoffset = scrollYOffset();
// bottom is doc height - window height - scroll offset
//var bottom = documentHeight() - lastHeight - yoffset
//if (yoffset > 0 || documentHeight() > lastHeight)
// bottom += 16; // allow for height of scrollbar
w3c_slidy.toolbar.style.bottom = 0; //bottom;
}
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden");
}
w3c_slidy.scrollhack = 0;
// set the keyboard focus to the help link on the
// toolbar to ensure that document has the focus
// IE doesn't always work with window.focus()
// and this hack has benefit of Enter for help
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
},
// invoked via F key
toggle_toolbar: function () {
if (!w3c_slidy.view_all)
{
if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden"))
{
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 1;
}
else
{
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 0;
}
}
},
scroll_x_offset: function () {
if (window.pageXOffset)
return self.pageXOffset;
if (document.documentElement &&
document.documentElement.scrollLeft)
return document.documentElement.scrollLeft;
if (document.body)
return document.body.scrollLeft;
return 0;
},
scroll_y_offset: function () {
if (window.pageYOffset)
return self.pageYOffset;
if (document.documentElement &&
document.documentElement.scrollTop)
return document.documentElement.scrollTop;
if (document.body)
return document.body.scrollTop;
return 0;
},
// looking for a way to determine height of slide content
// the slide itself is set to the height of the window
optimize_font_size: function () {
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
//var dh = documentHeight(); //getDocHeight(document);
var dh = slide.scrollHeight;
var wh = getWindowHeight();
var u = 100 * dh / wh;
alert("window utilization = " + u + "% (doc "
+ dh + " win " + wh + ")");
},
// from document object
get_doc_height: function (doc) {
if (!doc)
doc = document;
if (doc && doc.body && doc.body.offsetHeight)
return doc.body.offsetHeight; // ns/gecko syntax
if (doc && doc.body && doc.body.scrollHeight)
return doc.body.scrollHeight;
alert("couldn't determine document height");
},
get_window_height: function () {
if ( typeof( window.innerHeight ) == 'number' )
return window.innerHeight; // Non IE browser
if (document.documentElement && document.documentElement.clientHeight)
return document.documentElement.clientHeight; // IE6
if (document.body && document.body.clientHeight)
return document.body.clientHeight; // IE4
},
document_height: function () {
var sh, oh;
sh = document.body.scrollHeight;
oh = document.body.offsetHeight;
if (sh && oh)
{
return (sh > oh ? sh : oh);
}
// no idea!
return 0;
},
smaller: function () {
if (w3c_slidy.size_index > 0)
{
--w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
bigger: function () {
if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1)
{
++w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
// with thanks to Ivan Herman for the suggestion
adjust_object_dimensions: function (width, height) {
for( var i = 0; i < w3c_slidy.objects.length; i++ )
{
var obj = this.objects[i];
var mimeType = obj.getAttribute("type");
if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
{
if ( !obj.initialWidth )
obj.initialWidth = obj.getAttribute("width");
if ( !obj.initialHeight )
obj.initialHeight = obj.getAttribute("height");
if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
{
var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
var newW = width * (w/100.0);
obj.setAttribute("width",newW);
}
if ( obj.initialHeight &&
obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
{
var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
var newH = height * (h/100.0);
obj.setAttribute("height", newH);
}
}
}
},
// needed for Opera to inhibit default behavior
// since Opera delivers keyPress even if keyDown
// was cancelled
key_press: function (event) {
if (!event)
event = window.event;
if (!w3c_slidy.key_wanted)
return w3c_slidy.cancel(event);
return true;
},
// See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
key_down: function (event) {
var key;
w3c_slidy.key_wanted = true;
if (!event)
event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey || event.metaKey)
return true;
// dismiss table of contents if visible
if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40)
{
w3c_slidy.hide_table_of_contents();
if (key == 27 || key == 84 || key == 67)
return w3c_slidy.cancel(event);
}
if (key == 34) // Page Down
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.next_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 33) // Page Up
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.previous_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 32) // space bar
{
w3c_slidy.next_slide(true);
return w3c_slidy.cancel(event);
}
else if (key == 37) // Left arrow
{
w3c_slidy.previous_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 36) // Home
{
w3c_slidy.first_slide();
return w3c_slidy.cancel(event);
}
else if (key == 35) // End
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 39) // Right arrow
{
w3c_slidy.next_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 13) // Enter
{
if (w3c_slidy.outline)
{
if (w3c_slidy.outline.visible)
w3c_slidy.fold(w3c_slidy.outline);
else
w3c_slidy.unfold(w3c_slidy.outline);
return w3c_slidy.cancel(event);
}
}
else if (key == 188) // < for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 190) // > for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 189 || key == 109) // - for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 83) // S for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 66) // B for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 90) // Z for last slide
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 70) // F for toggle toolbar
{
w3c_slidy.toggle_toolbar();
return w3c_slidy.cancel(event);
}
else if (key == 65) // A for toggle view single/all slides
{
w3c_slidy.toggle_view();
return w3c_slidy.cancel(event);
}
else if (key == 75) // toggle action of left click for next page
{
w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled;
var alert_msg = (w3c_slidy.mouse_click_enabled ?
"enabled" : "disabled") + " mouse click advance";
alert(alert_msg.localize());
return w3c_slidy.cancel(event);
}
else if (key == 84 || key == 67) // T or C for table of contents
{
if (w3c_slidy.toc)
w3c_slidy.toggle_table_of_contents();
return w3c_slidy.cancel(event);
}
else if (key == 72) // H for help
{
window.location = w3c_slidy.help_page;
return w3c_slidy.cancel(event);
}
//else alert("key code is "+ key);
return true;
},
// safe for both text/html and application/xhtml+xml
create_element: function (name) {
if (this.xhtml && (typeof document.createElementNS != 'undefined'))
return document.createElementNS("http://www.w3.org/1999/xhtml", name)
return document.createElement(name);
},
get_element_style: function (elem, IEStyleProp, CSSStyleProp) {
if (elem.currentStyle)
{
return elem.currentStyle[IEStyleProp];
}
else if (window.getComputedStyle)
{
var compStyle = window.getComputedStyle(elem, "");
return compStyle.getPropertyValue(CSSStyleProp);
}
return "";
},
// the string str is a whitespace separated list of tokens
// test if str contains a particular token, e.g. "slide"
has_token: function (str, token) {
if (str)
{
// define pattern as regular expression
var pattern = /\w+/g;
// check for matches
// place result in array
var result = str.match(pattern);
// now check if desired token is present
for (var i = 0; i < result.length; i++)
{
if (result[i] == token)
return true;
}
}
return false;
},
get_class_list: function (element) {
if (typeof element.className != 'undefined')
return element.className;
return element.getAttribute("class");
},
has_class: function (element, name) {
if (element.nodeType != 1)
return false;
var regexp = new RegExp("(^| )" + name + "\W*");
if (typeof element.className != 'undefined')
return regexp.test(element.className);
return regexp.test(element.getAttribute("class"));
},
remove_class: function (element, name) {
var regexp = new RegExp("(^| )" + name + "\W*");
var clsval = "";
if (typeof element.className != 'undefined')
{
clsval = element.className;
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.className = clsval;
}
}
else
{
clsval = element.getAttribute("class");
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.setAttribute("class", clsval);
}
}
},
add_class: function (element, name) {
if (!this.has_class(element, name))
{
if (typeof element.className != 'undefined')
element.className += " " + name;
else
{
var clsval = element.getAttribute("class");
clsval = clsval ? clsval + " " + name : name;
element.setAttribute("class", clsval);
}
}
},
// HTML elements that can be used with class="incremental"
// note that you can also put the class on containers like
// up, ol, dl, and div to make their contents appear
// incrementally. Upper case is used since this is what
// browsers report for HTML node names (text/html).
incremental_elements: null,
okay_for_incremental: function (name) {
if (!this.incremental_elements)
{
var inclist = new Array();
inclist["p"] = true;
inclist["pre"] = true;
inclist["li"] = true;
inclist["blockquote"] = true;
inclist["dt"] = true;
inclist["dd"] = true;
inclist["h2"] = true;
inclist["h3"] = true;
inclist["h4"] = true;
inclist["h5"] = true;
inclist["h6"] = true;
inclist["span"] = true;
inclist["address"] = true;
inclist["table"] = true;
inclist["tr"] = true;
inclist["th"] = true;
inclist["td"] = true;
inclist["img"] = true;
inclist["object"] = true;
this.incremental_elements = inclist;
}
return this.incremental_elements[name.toLowerCase()];
},
next_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.next_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1) // ELEMENT
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
previous_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.previous_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1)
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
// set visibility for all elements on current slide with
// a parent element with attribute class="incremental"
set_visibility_all_incremental: function (value) {
var node = this.next_incremental_item(null);
if (value == "hidden")
{
while (node)
{
w3c_slidy.add_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
else // value == "visible"
{
while (node)
{
w3c_slidy.remove_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
},
// reveal the next hidden item on the slide
// node is null or the node that was last revealed
reveal_next_item: function (node) {
node = w3c_slidy.next_incremental_item(node);
if (node && node.nodeType == 1) // an element
w3c_slidy.remove_class(node, "invisible");
return node;
},
// exact inverse of revealNextItem(node)
hide_previous_item: function (node) {
if (node && node.nodeType == 1) // an element
w3c_slidy.add_class(node, "invisible");
return this.previous_incremental_item(node);
},
// left to right traversal of root's content
next_node: function (root, node) {
if (node == null)
return root.firstChild;
if (node.firstChild)
return node.firstChild;
if (node.nextSibling)
return node.nextSibling;
for (;;)
{
node = node.parentNode;
if (!node || node == root)
break;
if (node && node.nextSibling)
return node.nextSibling;
}
return null;
},
// right to left traversal of root's content
previous_node: function (root, node) {
if (node == null)
{
node = root.lastChild;
if (node)
{
while (node.lastChild)
node = node.lastChild;
}
return node;
}
if (node.previousSibling)
{
node = node.previousSibling;
while (node.lastChild)
node = node.lastChild;
return node;
}
if (node.parentNode != root)
return node.parentNode;
return null;
},
previous_sibling_element: function (el) {
el = el.previousSibling;
while (el && el.nodeType != 1)
el = el.previousSibling;
return el;
},
next_sibling_element: function (el) {
el = el.nextSibling;
while (el && el.nodeType != 1)
el = el.nextSibling;
return el;
},
first_child_element: function (el) {
var node;
for (node = el.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1)
break;
}
return node;
},
first_tag: function (element, tag) {
var node;
if (!this.is_xhtml)
tag = tag.toUpperCase();
for (node = element.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1 && node.nodeName == tag)
break;
}
return node;
},
hide_selection: function () {
if (window.getSelection) // Firefox, Chromium, Safari, Opera
{
var selection = window.getSelection();
if (selection.rangeCount > 0)
{
var range = selection.getRangeAt(0);
range.collapse (false);
}
}
else // Internet Explorer
{
var textRange = document.selection.createRange ();
textRange.collapse (false);
}
},
get_selected_text: function () {
try
{
if (window.getSelection)
return window.getSelection().toString();
if (document.getSelection)
return document.getSelection().toString();
if (document.selection)
return document.selection.createRange().text;
}
catch (e)
{
}
return "";
},
// make note of length of selected text
// as this evaluates to zero in click event
mouse_button_up: function (e) {
w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length;
},
// right mouse button click is reserved for context menus
// it is more reliable to detect rightclick than leftclick
mouse_button_click: function (e) {
var rightclick = false;
var leftclick = false;
var middleclick = false;
var target;
if (!e)
var e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target.nodeType == 3)
target = target.parentNode;
if (e.which) // all browsers except IE
{
leftclick = (e.which == 1);
middleclick = (e.which == 2);
rightclick = (e.which == 3);
}
else if (e.button)
{
// Konqueror gives 1 for left, 4 for middle
// IE6 gives 0 for left and not 1 as I expected
if (e.button == 4)
middleclick = true;
// all browsers agree on 2 for right button
rightclick = (e.button == 2);
}
else leftclick = true;
/*
alert("you clicked over a " + target.nodeName + " element\n" +
"w3c_slidy.mouse_click_enabled = " + w3c_slidy.mouse_click_enabled + "\n" +
"leftclick = " + leftclick + "\n" +
"selected text length = " + w3c_slidy.selected_text_len);
//alert("selected text length = " + w3c_slidy.selected_text_len);
*/
if (w3c_slidy.selected_text_len > 0)
{
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
// dismiss table of contents
w3c_slidy.hide_table_of_contents();
// check if target is something that probably want's clicks
// e.g. a, embed, object, input, textarea, select, option
var tag = target.nodeName.toLowerCase();
if (w3c_slidy.mouse_click_enabled && leftclick &&
tag != "a" &&
tag != "embed" &&
tag != "object" &&
tag != "video" &&
tag != "input" &&
tag != "textarea" &&
tag != "select" &&
tag != "option" &&
!target.onclick)
{
w3c_slidy.next_slide(true);
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
},
get_key: function (e)
{
var key;
// kludge around NS/IE differences
if (typeof window.event != "undefined")
key = window.event.keyCode;
else if (e.which)
key = e.which;
return key;
},
get_target: function (e) {
var target;
if (!e)
e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
if (target.nodeType != 1)
target = target.parentNode;
return target;
},
// does display property provide correct defaults?
is_block: function (elem) {
var tag = elem.nodeName.toLowerCase();
return tag == "ol" || tag == "ul" || tag == "p" ||
tag == "li" || tag == "table" || tag == "pre" ||
tag == "h1" || tag == "h2" || tag == "h3" ||
tag == "h4" || tag == "h5" || tag == "h6" ||
tag == "blockquote" || tag == "address";
},
add_listener: function (element, event, handler) {
if (window.addEventListener)
element.addEventListener(event, handler, false);
else
element.attachEvent("on"+event, handler);
},
// used to prevent event propagation from field controls
stop_propagation: function (event) {
event = event ? event : window.event;
event.cancelBubble = true; // for IE
if (event.stopPropagation)
event.stopPropagation();
return true;
},
cancel: function (event) {
if (event)
{
event.cancel = true;
event.returnValue = false;
if (event.preventDefault)
event.preventDefault();
}
w3c_slidy.key_wanted = false;
return false;
}
};
// for each language define an associative array
// and also the help text which is longer
var w3c_slidy_i18n = {
strings_es: {
"slide":"pág.",
"help?":"Ayuda",
"contents?":"Índice",
"table of contents":"tabla de contenidos",
"Table of Contents":"Tabla de Contenidos",
"restart presentation":"Reiniciar presentación",
"restart?":"Inicio"
},
help_es:
"Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
"o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.",
strings_ca: {
"slide":"pàg..",
"help?":"Ajuda",
"contents?":"Índex",
"table of contents":"taula de continguts",
"Table of Contents":"Taula de Continguts",
"restart presentation":"Reiniciar presentació",
"restart?":"Inici"
},
help_ca:
"Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
"o Re pàg y Av pàg. Usi S i B per canviar grandària de font.",
strings_cs: {
"slide":"snímek",
"help?":"nápověda",
"contents?":"obsah",
"table of contents":"obsah prezentace",
"Table of Contents":"Obsah prezentace",
"restart presentation":"znovu spustit prezentaci",
"restart?":"restart"
},
help_cs:
"Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " +
"šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " +
"dá zvětšit a zmenšit pomocí kláves B a S.",
strings_nl: {
"slide":"pagina",
"help?":"Help?",
"contents?":"Inhoud?",
"table of contents":"inhoudsopgave",
"Table of Contents":"Inhoudsopgave",
"restart presentation":"herstart presentatie",
"restart?":"Herstart?"
},
help_nl:
"Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
"of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.",
strings_de: {
"slide":"Seite",
"help?":"Hilfe",
"contents?":"Übersicht",
"table of contents":"Inhaltsverzeichnis",
"Table of Contents":"Inhaltsverzeichnis",
"restart presentation":"Präsentation neu starten",
"restart?":"Neustart"
},
help_de:
"Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
"Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.",
strings_pl: {
"slide":"slajd",
"help?":"pomoc?",
"contents?":"spis treści?",
"table of contents":"spis treści",
"Table of Contents":"Spis Treści",
"restart presentation":"Restartuj prezentację",
"restart?":"restart?"
},
help_pl:
"Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
"lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.",
strings_fr: {
"slide":"page",
"help?":"Aide",
"contents?":"Index",
"table of contents":"table des matières",
"Table of Contents":"Table des matières",
"restart presentation":"Recommencer l'exposé",
"restart?":"Début"
},
help_fr:
"Naviguez avec la souris, la barre d'espace, les flèches " +
"gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
"les touches S et B pour modifier la taille de la police.",
strings_hu: {
"slide":"oldal",
"help?":"segítség",
"contents?":"tartalom",
"table of contents":"tartalomjegyzék",
"Table of Contents":"Tartalomjegyzék",
"restart presentation":"bemutató újraindítása",
"restart?":"újraindítás"
},
help_hu:
"Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
"használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
"Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
"a szöveg méretét.",
strings_it: {
"slide":"pag.",
"help?":"Aiuto",
"contents?":"Indice",
"table of contents":"indice",
"Table of Contents":"Indice",
"restart presentation":"Ricominciare la presentazione",
"restart?":"Inizio"
},
help_it:
"Navigare con mouse, barra spazio, frecce sinistra/destra o " +
"PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.",
strings_el: {
"slide":"σελίδα",
"help?":"βοήθεια;",
"contents?":"περιεχόμενα;",
"table of contents":"πίνακας περιεχομένων",
"Table of Contents":"Πίνακας Περιεχομένων",
"restart presentation":"επανεκκίνηση παρουσίασης",
"restart?":"επανεκκίνηση;"
},
help_el:
"Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
"ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
"το μέγεθος της γραμματοσειράς.",
strings_ja: {
"slide":"スライド",
"help?":"ヘルプ",
"contents?":"目次",
"table of contents":"目次を表示",
"Table of Contents":"目次",
"restart presentation":"最初から再生",
"restart?":"最初から"
},
help_ja:
"マウス左クリック ・ スペース ・ 左右キー " +
"または Page Up ・ Page Downで操作, S ・ Bでフォントサイズ変更",
strings_zh: {
"slide":"幻灯片",
"help?":"帮助?",
"contents?":"内容?",
"table of contents":"目录",
"Table of Contents":"目录",
"restart presentation":"重新启动展示",
"restart?":"重新启动?"
},
help_zh:
"用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
"用 S, B 改变字体大小.",
strings_ru: {
"slide":"слайд",
"help?":"помощь?",
"contents?":"содержание?",
"table of contents":"оглавление",
"Table of Contents":"Оглавление",
"restart presentation":"перезапустить презентацию",
"restart?":"перезапуск?"
},
help_ru:
"Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
"влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.",
strings_sv: {
"slide":"sida",
"help?":"hjälp",
"contents?":"innehåll",
"table of contents":"innehållsförteckning",
"Table of Contents":"Innehållsförteckning",
"restart presentation":"visa presentationen från början",
"restart?":"börja om"
},
help_sv:
"Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " +
"vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " +
"Använd tangenterna S och B för att ändra textens storlek.",
// each such language array is declared in the localize array
// which is set on string prototype and used as in "foo".localize();
localize: {
"es":this.strings_es,
"ca":this.strings_ca,
"cs":this.strings_cs,
"nl":this.strings_nl,
"de":this.strings_de,
"pl":this.strings_pl,
"fr":this.strings_fr,
"hu":this.strings_hu,
"it":this.strings_it,
"el":this.strings_el,
"jp":this.strings_ja,
"zh":this.strings_zh,
"ru":this.strings_ru,
"sv":this.strings_sv
},
init: function () {
var i18n = w3c_slidy_i18n;
var help_text = w3c_slidy.help_text;
i18n.strings_es[help_text] = i18n.help_es;
i18n.strings_ca[help_text] = i18n.help_ca;
i18n.strings_cs[help_text] = i18n.help_cs;
i18n.strings_nl[help_text] = i18n.help_nl;
i18n.strings_de[help_text] = i18n.help_de;
i18n.strings_pl[help_text] = i18n.help_pl;
i18n.strings_fr[help_text] = i18n.help_fr;
i18n.strings_hu[help_text] = i18n.help_hu;
i18n.strings_it[help_text] = i18n.help_it;
i18n.strings_el[help_text] = i18n.help_el;
i18n.strings_ja[help_text] = i18n.help_ja;
i18n.strings_zh[help_text] = i18n.help_zh;
i18n.strings_ru[help_text] = i18n.help_ru;
i18n.strings_sv[help_text] = i18n.help_sv;
w3c_slidy.lang = document.body.parentNode.getAttribute("lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = "en";
// add localize method to all strings
// for use as in "contents".localize()
String.prototype.localize = function() {
if (this == "")
return this;
// try full language code, e.g. en-US
var s, lookup = w3c_slidy_i18n.localize[w3c_slidy.lang];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
// strip country code suffix, e.g.
// try en if undefined for en-US
var lg = w3c_slidy.lang.split("-");
if (lg.length > 1)
{
lookup = w3c_slidy_i18n.localize[lg[0]];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
}
// otherwise string as is
return this;
};
}
};
// hack for back button behavior
if (w3c_slidy.ie6 || w3c_slidy.ie7)
{
document.write("<iframe id='historyFrame' " +
"src='javascript:\"<html"+"></"+"html>\"' " +
"height='1' width='1' " +
"style='position:absolute;left:-800px'></iframe>");
}
// attach event listeners for initialization
w3c_slidy.set_up();
// hide the slides as soon as body element is available
// to reduce annoying screen mess before the onload event
setTimeout(w3c_slidy.hide_slides, 50);
/*]]>*/
</script>
</head>
<body class="article">
<div id="header" class="slide">
<h1>JavaScript I - Variables, Functions, and Scope</h1>
<span id="author">Bruce Harris, 7/31/12</span><br />
</div>
<div class="sect1 slide">
<h1 id="_content_and_target_audience">Content and Target Audience</h1>
<div class="sectionbody">
<div class="paragraph"><p>Emphasis on behavior/syntax specific to JavaScript (as compared to other languages).</p></div>
<div class="paragraph"><p>JavaScript experience not required, but
you have experience programming in a C style language.</p></div>
<div class="paragraph"><p>Output of code snippet below is obvious to you.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="c1">// document.writeln is a printing function</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="s2">&quot;, &quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_resources_and_tools">Resources and Tools</h1>
<div class="sectionbody">
<ul class="">
<li>
<span>
These slides: <a href="http://bruceharris.net/techtalks/">http://bruceharris.net/techtalks</a>
</span>
</li>
<li>
<span>
Sandbox: <a href="http://codepen.io/pen">CodePen</a>
</span>
</li>
<li>
<span>
Reference: <a href="https://developer.mozilla.org/en/JavaScript/">Mozilla Developer Network</a>
</span>
</li>
<li>
<span>
Instruction (online book): <a href="http://eloquentjavascript.net/contents.html">Eloquent JavaScript</a>
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_not_as_i_do_8230">Not as I do&#8230;</h1>
<div class="sectionbody">
<div class="paragraph"><p>Avoid <tt>document.writeln()</tt> - not useful in real life, but useful for examples</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_the_tt_var_tt_keyword">The <tt>var</tt> keyword</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_is_tt_var_tt_optional">Is <tt>var</tt> Optional?</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// hmmmmmm.....</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
<div class="paragraph incremental"><p>Above code works, but is <strong>evil</strong>. Assigning variables without declaration using
<tt>var</tt> creates <em>global</em> variables regardless of where they are declared (this is
usually a very bad thing).</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_the_tt_typeof_tt_operator">The <tt>typeof</tt> operator</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">s</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">s</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_dynamic_typing">Dynamic Typing</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
<span class="nx">x</span> <span class="o">=</span> <span class="s2">&quot;hello&quot;</span><span class="p">;</span> <span class="c1">// can we change a number to a string?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mf">1.1</span><span class="p">;</span> <span class="c1">// is a decimal different from an integer?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_statement">Function Statement</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">print</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// note no semicolon</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_expression">Function Expression</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="c1">// anonymous function</span>
<span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_functions_as_a_href_http_en_wikipedia_org_wiki_first_class_citizen_first_class_citizens_a">Functions as <a href="http://en.wikipedia.org/wiki/First-class_citizen">First Class Citizens</a></h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="c1">// capture function in variable</span>
<span class="kd">var</span> <span class="nx">print</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_passing_a_function_as_an_argument_to_another_function">Passing a Function as an Argument to Another Function</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">print</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">italic</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="s1">&#39;&lt;em&gt;&#39;</span> <span class="o">+</span> <span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;/em&gt;&#39;</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">callFunc</span><span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">arg</span><span class="p">){</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">callFunc</span><span class="p">(</span><span class="nx">print</span><span class="p">,</span> <span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="nx">italic</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">));</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_returning_a_function_from_a_function">Returning a function from a function</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">print</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;br&gt;&#39;</span><span class="p">);</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">italic</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="s1">&#39;&lt;em&gt;&#39;</span> <span class="o">+</span> <span class="nx">x</span> <span class="o">+</span> <span class="s1">&#39;&lt;/em&gt;&#39;</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">makeCompoundFunction</span><span class="p">(</span><span class="nx">outer</span><span class="p">,</span> <span class="nx">inner</span><span class="p">){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">outer</span><span class="p">(</span><span class="nx">inner</span><span class="p">(</span><span class="nx">arg</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">printItalic</span> <span class="o">=</span> <span class="nx">makeCompoundFunction</span><span class="p">(</span><span class="nx">print</span><span class="p">,</span> <span class="nx">italic</span><span class="p">);</span>
<span class="nx">print</span><span class="p">(</span><span class="s2">&quot;hello&quot;</span><span class="p">);</span>
<span class="nx">printItalic</span><span class="p">(</span><span class="s2">&quot;world&quot;</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_block_scope_v_function_scope">Block Scope v. Function Scope</h1>
<div class="sectionbody">
<div class="paragraph"><p>Most C style languages have <em>block</em> scope.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// did we change x or create a new x?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_scope">Function Scope</h1>
<div class="sectionbody">
<div class="paragraph"><p>JavaScript <em>does not have block scope</em>, it has only <em>function scope</em></p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// did we change x or create a new x?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_lexical_scoping_v_dynamic_scoping">Lexical Scoping v. Dynamic Scoping</h1>
<div class="sectionbody">
<div class="paragraph"><p>Most C style languages have
<a href="http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping">Lexical Scoping</a>.
So does JavaScript.</p></div>
<ul class=" incremental">
<li>
<span>
Every function creates its own scope environment
</span>
</li>
<li>
<span>
Variables declared inside a function are&#8230;
</span>
<ul class="">
<li>
<span>
visible everywhere inside that function
</span>
</li>
<li>
<span>
not visible outside that function
</span>
</li>
</ul>
</li>
<li>
<span>
Variables (or functions) declared outside of any function are <em>global</em>
</span>
</li>
</ul>
<div class="paragraph incremental"><p>More specifically&#8230;</p></div>
<ul class=" incremental">
<li>
<span>
In JavaScript functions can be nested inside other functions
</span>
</li>
<li>
<span>
A function has access to the scope environment of its parent function(s)
</span>
</li>
<li>
<span>
Thus, variables declared inside a function are visible inside functions nested inside the same function
</span>
</li>
</ul>
<div class="paragraph incremental"><p>Closure</p></div>
<ul class=" incremental">
<li>
<span>
Scope environment created by a function can persist even after function finishes executing
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_declare_x_in_global_scope">Declare x in global scope</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_declare_x_in_function_scope">Declare x in function scope</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span> <span class="c1">// will this work?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_declare_x_in_global_scope_and_in_function_scope">Declare x in global scope and in function scope</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_declare_x_in_global_scope_and_as_function_parameter">Declare x in global scope and as function parameter</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_reference_x_in_function_scope_without_tt_var_tt_keyword">Reference x in function scope without <tt>var</tt> keyword</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span>
<span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// is this a good idea?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span> <span class="c1">// will this work?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_declare_nested_function_and_call_it_outside">Declare nested function and call it outside</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f1</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f2</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">f2</span><span class="p">();</span> <span class="c1">// will this work?</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_declare_nested_function_and_call_it_inside">Declare nested function and call it inside</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f1</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">f2</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">f2</span><span class="p">();</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">f1</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_closure">Closure</h1>
<div class="sectionbody">
<div class="paragraph"><p>Environment created by invoking a function persists even after
function is finished executing.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeAccumulator</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">x</span> <span class="o">+=</span> <span class="nx">n</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">x</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">accum</span> <span class="o">=</span> <span class="nx">makeAccumulator</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum</span><span class="p">(</span><span class="mi">13</span><span class="p">));</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_closure_creates_a_new_persistent_environment">Closure creates a new persistent environment</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeAccumulator</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">x</span> <span class="o">+=</span> <span class="nx">n</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">x</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">accum1</span> <span class="o">=</span> <span class="nx">makeAccumulator</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum1</span><span class="p">(</span><span class="mi">5</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum1</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span>
<span class="kd">var</span> <span class="nx">accum2</span> <span class="o">=</span> <span class="nx">makeAccumulator</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum2</span><span class="p">(</span><span class="mi">23</span><span class="p">));</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">accum2</span><span class="p">(</span><span class="mi">17</span><span class="p">));</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_hoisting">Function Hoisting</h1>
<div class="sectionbody">
<div class="paragraph"><p><strong>Most important difference</strong> between function statements and function expressions:</p></div>
<div class="paragraph"><p>Function statements are "hoisted" to the top of the scope in
which they appear. Regardless of where they appear within a scope environment,
it is as if they were declared at the top of that scope environment.</p></div>
<div class="paragraph"><p>Function expressions are <em>not</em> hoisted.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">f1</span><span class="p">;</span>
<span class="nx">f1</span><span class="p">();</span> <span class="c1">// can we call f1 before function expression assignment?</span>
<span class="nx">f1</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">f2</span><span class="p">();</span> <span class="c1">// can we call f2 before its declaration via function statement?</span>
<span class="kd">function</span> <span class="nx">f2</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">}</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_function_expressions_are_em_not_em_hoisted">Function expressions are <em>not</em> hoisted</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">f</span><span class="p">;</span>
<span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">2</span><span class="p">;</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span>
<span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_hoisting_can_cause_unintuitive_behavior">Hoisting can cause unintuitive behavior</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">f</span><span class="p">;</span>
<span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span> <span class="k">return</span> <span class="mi">2</span><span class="p">;</span> <span class="p">};</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){</span> <span class="k">return</span> <span class="mi">1</span> <span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">f</span><span class="p">());</span> <span class="c1">// did we re-assign f?</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_immediate_function">Immediate function</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="o">=</span> <span class="s2">&quot;cool, no global variables!&quot;</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>
<span class="p">})();</span> <span class="c1">// anonymous function invoked immediately</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_1">Exercise 1</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeAdder</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">add7</span> <span class="o">=</span> <span class="nx">makeAdder</span><span class="p">(</span><span class="mi">7</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add7</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span> <span class="c1">// 11</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add7</span><span class="p">(</span><span class="mi">9</span><span class="p">));</span> <span class="c1">// 16</span>
<span class="kd">var</span> <span class="nx">add3</span> <span class="o">=</span> <span class="nx">makeAdder</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add3</span><span class="p">(</span><span class="mi">6</span><span class="p">));</span> <span class="c1">// 9</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">add3</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="c1">// 5</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_2">Exercise 2</h1>
<div class="sectionbody">
<div class="paragraph"><p>Not practical, but a good exercise in functional programming</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">var</span> <span class="nx">sum1</span> <span class="o">=</span> <span class="p">(</span>
<span class="c1">// your code here</span>
<span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">sum1</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)());</span> <span class="c1">// 7</span>
<span class="kd">var</span> <span class="nx">sum2</span> <span class="o">=</span> <span class="p">(</span>
<span class="c1">// your code here</span>
<span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">sum2</span><span class="p">()(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">));</span> <span class="c1">// 7</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_3">Exercise 3</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">makeCounter</span><span class="p">(</span><span class="nx">start</span><span class="p">,</span> <span class="nx">increment</span><span class="p">){</span>
<span class="c1">// your code here</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">counter1</span> <span class="o">=</span> <span class="nx">makeCounter</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter1</span><span class="p">());</span> <span class="c1">// 100</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter1</span><span class="p">());</span> <span class="c1">// 101</span>
<span class="kd">var</span> <span class="nx">counter2</span> <span class="o">=</span> <span class="nx">makeCounter</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter2</span><span class="p">());</span> <span class="c1">// 10</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">counter2</span><span class="p">());</span> <span class="c1">// 15</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_4">Exercise 4</h1>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre><span class="kd">function</span> <span class="nx">add</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">+</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">subtract</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span> <span class="o">-</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// operation is either &#39;+&#39; or &#39;-&#39;</span>
<span class="kd">function</span> <span class="nx">makeReducer</span><span class="p">(</span><span class="nx">operation</span><span class="p">){</span>
<span class="c1">// your code here, preferably just one line</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">plus</span> <span class="o">=</span> <span class="nx">makeReducer</span><span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">plus</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">));</span> <span class="c1">// 9</span>
<span class="kd">var</span> <span class="nx">minus</span> <span class="o">=</span> <span class="nx">makeReducer</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">writeln</span><span class="p">(</span><span class="nx">minus</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">));</span> <span class="c1">// -1</span>
</pre></div></div></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_exercise_5">Exercise 5</h1>
<div class="sectionbody">
<div class="paragraph"><p>Modify solution to Exercise 4 to remove <tt>add</tt> and <tt>subtract</tt> from the global scope</p></div>
</div>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment