Page 1
Becoming a JavaScript Wizard
Bryan Basham
Software Alchemist
[email protected]
http://www.linkedin.com/in/SoftwareAlchemist
Colorado Software Summit: October 19 – 24, 2008 © Copyright 2008, Bryan Basham
Bryan Basham — Becoming a JavaScript Wizard Slide 1
Page 2
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 2
© Copyright 2008, Bryan Basham
Topics Mind Map
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 3
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 3
© Copyright 2008, Bryan Basham
Using Web Standards
Separation of Concerns: structure, presentation, and behavior
Why?
Supports multiple browsers and devices
Easy to modify and replace look and feel
Clarity of code
Brevity of code (reduces bandwidth)
Better accessibility and usability
“Write once, publish everywhere”
Page 4
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 4
© Copyright 2008, Bryan Basham
Example / Demo
Page 5
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 5
© Copyright 2008, Bryan Basham
Structure
XHTML (or HTML v4.01)
Markup validation
Semantic (not presentational) structure
<body> <div id='header'> <h1>MyCorp</h1> <ul id='main_navigation_list'> <li><a href='...'>Exams</a></li> <li><a href='...'>Surveys</a></li> </ul> </div> <div id='content'> <p>....</p> </div> ...</body>
Page 6
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 6
© Copyright 2008, Bryan Basham
Presentation
Cascading Style Sheets (CSS)
Extremely powerful layout and styling
ul#main_navigation_list { list-style: none; margin: 0 0 0 110px; overflow: hidden; padding: 25px 0 0 0; width: 100%;}ul#main_navigation_list li { float: left; margin: 0; padding: 0 .5em;}ul#main_navigation_list li a { color:#fff; text-decoration: none;}
Page 7
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 7
© Copyright 2008, Bryan Basham
Behavior
JavaScript (aka ECMAScript 262)
Rich object-based and functional language
Manipulate the page structure (DOM)
Handle user-generated events on elements
Handle sync and async communication with server
CONS: some inconsistencies between browsers
Page 8
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 8
© Copyright 2008, Bryan Basham
Why is this important?
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
Client
Server
UI Code
Data
Behavior
StructureStructure
Presentation
Behavior
Data
conversion
invoke
select next view
generate
enhanc
e
style / layout
Page 9
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 9
© Copyright 2008, Bryan Basham
Topics Mind Map
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 10
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 10
© Copyright 2008, Bryan Basham
Data Types
Numbers (64-bit floating point)42 * 10.0 ==> 420typeof 42 ==> "number"typeof 4.2 ==> "number"
Strings (Unicode, ' and " delimited)"foo"'she said "he said"'typeof "foo" ==> "string"
Booleans (true and false, yes/no, 1/0)typeof true ==> "boolean"
Page 11
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 11
© Copyright 2008, Bryan Basham
Data Types
Arrays
Objects
Functions
nulltypeof null ==> "object"
undefined typeof undefined ==> "undefined"
Page 12
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 12
© Copyright 2008, Bryan Basham
Variables
Globalsvar G1 = 47;G2 = 100;
Localsfunction f() { var L1 = 47; return L1 + G1;}function g() { var G1 = 420; // this has local scope function h() { var G1 = 42; // nested scoping return G1; } return G1 + h();}g() ==> 462
Page 13
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 13
© Copyright 2008, Bryan Basham
Namespace
Globals (vars and functions) create clutter
Helpful idiom:
var MySpace = {
G1 : 42,
square : function(x) { return x * x; },
configuration : { width : 100, height : 350 },
funct : function(x) { return MySpace.G1 * x; }}
MySpace.funct(10) ==> 420
Page 14
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 14
© Copyright 2008, Bryan Basham
Arrays
Syntaxvar myArray = [13, 42, 47, 420];typeof myArray ==> "object" // Huh???
AccessmyArray.length ==> 4myArray[0] ==> 13myArray[3] ==> 420
Iterationfor ( var i=0; i<myArray.length; i++ ) { console.info("myArray[" + i + "] is " + myArray[i]);}
Page 15
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 15
© Copyright 2008, Bryan Basham
Functions
Definition syntaxfunction square(x) { return x * x; }square(12) ==> 144typeof square ==> "function"
OR as a variablevar square = function(x) { return x * x; }; // lambda function (LISP)square(12) ==> 144
OR as an objectvar square = new Function("x", "return x * x;");square(12) ==> 144
Page 16
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 16
© Copyright 2008, Bryan Basham
Functional Programming
Functions are first-class citizens
Example 1:function each(funct, array) { for ( var i=0; i<array.length; i++ ) { funct(array[i]); }}each( function(x) { console.info(x); }, myArray );
Example 2:function map(funct, array) { var newArray = new Array(); for ( var i=0; i<array.length; i++ ) { newArray[i] = funct(array[i]); } return newArray;}map( square, myArray ); ==> [169, 1764, 2209, 176400]
Page 17
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 17
© Copyright 2008, Bryan Basham
Closures
Closures hold state within a functionfunction square(x) { return x * x;}
function makeCutoffFunction(nTimes, funct) { return function(x) { // creating a new function object nTimes--; // access to local state variable if ( nTimes >= 0 ) { return funct(x); // do the funct once } };}
var squareOnce = makeCutoffFunction( 1, square );squareOnce(12) ==> 144squareOnce(13) ==> void
var logThrice = makeCutoffFunction( 3, console.info );logThrice("first log message"); // log oncelogThrice("second log message"); // log twicelogThrice("third log message"); // log thricelogThrice("fourth log message"); // stops logging
Page 18
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 18
© Copyright 2008, Bryan Basham
Objects
Creating an objectvar O1 = new Object();O1.a = 47;O1.method = function() { console.info(this.a); };typeof O1 ==> "object"
OR as a literalvar O1 = { a : 47, method : function() { console.info(this.a); }}
Access object attributesO1.a ==> 47O1.a = 42;O1.method() ==> displays '42' in the consoleO1["a"] ==> 42O1["a"] = 420;O1["method"]() ==> displays '420' in the console
Page 19
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 19
© Copyright 2008, Bryan Basham
JavaScript Core Classes
Built-in
Object
Date
RegExp
Error (and subclasses)
Wrappers
String, Number, and Boolean
Odd balls
Function and Array
Page 20
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 20
© Copyright 2008, Bryan Basham
But wait... no classes
You can't create classes in JavaScriptclass Range { /* code here */ } // NOT VALID
You can only create object constructorstypeof Date ==> "function"
var Range = function(start, end) { this.start = start; this.end = end;}
var r1 = new Range(42, 47);r1.start ==> 42r1.end ==> 47
var r2 = new Range(13, 420);r2.start ==> 13r2.end ==> 420
r1 #111:Range
start = 42end = 47
r2 #222:Range
start = 13end = 420
Page 21
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 21
© Copyright 2008, Bryan Basham
Encapsulation
Ugh... these attributes are publicr2.start = 520;r2.start ==> 520 // Semantics broken: the “start” is now after the “end”
Closures allow us to hide private datavar Range = function(st, en) { var start = st; var end = en; this.getStart = function() { return start; } this.getEnd = function() { return end; }}
var r1 = new Range(42, 47);r1.start ==> undefinedr1.getStart() ==> 42r1.getEnd() ==> 47
var r2 = new Range(13, 420);r2.getStart() ==> 13r2.getEnd() ==> 420
Page 22
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 22
© Copyright 2008, Bryan Basham
Encapsulation object model
r1 #111:Range
getStartgetEnd
#987:CallObj
start = 42end = 47
#876:CallObj
start = 13end = 420
function() { return start; }
function() { return end; }
r2 #222:Range
getStartgetEnd
function() { return start; }
function() { return end; }
Page 23
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 23
© Copyright 2008, Bryan Basham
Encapsulation
Creating settersvar Range = function(start, end) {
this.getStart = function() { return start; }
this.setStart = function(x) { if ( x <= end ) start = x; }
this.getEnd = function() { return end; }
this.setEnd = function(x) { if ( x >= start ) end = x; }
}
var r = new Range(42, 47);
r.getStart() ==> 42
r.setStart(13)
r.getStart() ==> 13
r.setStart(50) // fails quietly; could throw an Error
r.getStart() ==> 13
Page 24
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 24
© Copyright 2008, Bryan Basham
But... this too has problems
This pattern creates lots of object-specific functions
r1 #111:Range
getStartsetStartgetEndsetEnd
#222:Range
getStartsetStartgetEndsetEnd
function() {...}
function(x) {...}
function() {...}
function(x) {...}
function() {...}
function(x) {...}
function() {...}
function(x) {...}
r2
#987:CallObj
start = 42end = 47
#876:CallObj
start = 13end = 420
Page 25
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 25
© Copyright 2008, Bryan Basham
Another class-like idiom
Constructors have prototypesvar Range = function(st, en) { this.start = st; this.end = en;}
// Setup shared Range object methodsRange.prototype.getStart = function() { return this.start; }Range.prototype.setStart = function(x) { if ( x <= this.end ) this.start = x;}Range.prototype.getEnd = function() { return this.end; }Range.prototype.setEnd = function(x) { if ( x >= this.start ) this.end = x;}
// Create a group of Range objectsvar r1 = new Range(42, 47);var r2 = new Range(13, 420);var r3 = new Range(1.2, 3.14);var r4 = new Range(1, 10);
Page 26
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 26
© Copyright 2008, Bryan Basham
Another class-like idiom
Function objects are reused across all objects
Range.prototype
getStartsetStartgetEndsetEnd
function() {...}
function(x) {...}
function() {...}
function(x) {...}
r1 #111:Range
start = 42end = 47
r2 #222:Range
start = 13end = 420
r3 #333:Range
start = 1.2end = 3.14
r4 #444:Range
start = 1end = 10
Page 27
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 27
© Copyright 2008, Bryan Basham
Hybrid OO idiom
var Circle = function(r) { // Private object attributes stored in the closure var radius = r; // Create privileged methods this.getRadius = function () { return radius; }}// Create public, but non-privileged methodsCircle.prototype.getDiameter = function() { return this.getRadius() * 2; }Circle.prototype.getArea = function() { return Circle.PI * this.getRadius() * this.getRadius(); }// Create class constantsCircle.PI = 3.14159;
var c1 = new Circle(4.2);c1.getRadius() ==> 4.2c1.getDiameter() ==> 8.4c1.getArea() ==> 55.4176476
var c2 = new Circle(10);c1.getRadius() ==> 10c1.getDiameter() ==> 20c1.getArea() ==> 314.159
Page 28
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 28
© Copyright 2008, Bryan Basham
Object model of hybrid OO
Circle.prototype
getDiametergetArea
function() {...}
function() {...}
c1 #111:Circle
getRadius
#987:CallObj
radius = 4.2
#876:CallObj
radius = 13
c2 #222:Circle
getRadius function() { return radius; }
function() { return radius; }
Page 29
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 29
© Copyright 2008, Bryan Basham
Advanced Class Features
Admittedly these “class-like” programming idioms are awkward
Mimicking class inheritance is even more complex
There are other, more advanced, inheritance mechanisms
Such as Prototypal inheritance
See Douglas Crawford on Resource (web) slide
Page 30
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 30
© Copyright 2008, Bryan Basham
JavaScript Object Notation
JSON is the ability to convert strings to and from JavaScript objects.
var obj = { a: 42, b: “foo” };var objStr = JSON.stringify(obj); // "{"a":42,"b":"foo"}"var o2 = JSON.parse(objStr);o1 == o2; // falseo1 === o2; // false
But what about our objects?var c1 = new Circle(4.2);
var c1Str = JSON.stringify(c1); // "{}" WTF?!?! Where's my object?
Page 31
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 31
© Copyright 2008, Bryan Basham
Hybrid-Class JSON Methods// If the class already exists, skipif ( ! Circle ) {
// Create the Circle class constructor function Circle(r) { ... };
// JSON related methods Circle.prototype.toJSON = function() { var dataString = this.getRadius().toJSON(); return MyJSON.makeClassWrapper("Circle", dataString); }; // The MyJSON class reviver function uses this static function Circle.parseJSON = function(dataString) { var radius = parseInt(dataString); return new Circle(radius); };
// Run unit tests var c = new Circle(42); var cStr = JSON.stringify(c); var newC = MyJSON.parse(cStr);
} // END of Circle definition check
Page 32
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 32
© Copyright 2008, Bryan Basham
JSON for Circle
The Circle instance method toJSON performs
conversion from object to string.var c1 = new Circle(42);c1.getArea(); // 5541.76476var c1Str = JSON.stringify(obj); // '"\"Circle(42)\""'
The MyJSON.parse method uses a JSON reviver
to reconstruct these objects.var newC1 = MyJSON.parse(c1Str);newC1.getArea(); // 5541.76476
The Circle static method parseJSON performs
conversion from string to object.
Page 33
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 33
© Copyright 2008, Bryan Basham
Topics Mind Map
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 34
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 34
© Copyright 2008, Bryan Basham
Client-Side Overview
The window object
The document object
The event model
Timed events
Ajax
Page 35
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 35
© Copyright 2008, Bryan Basham
Window
The window object is the “global object”
Control methods: close, focus, blur, move, open, print, resize
window
navigator
frames[]
location
history
document
screen
Page 36
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 36
© Copyright 2008, Bryan Basham
Document
The document object represents the
structure of the web page
Provides easy access to critical elements
document
anchors[]
applets[]
forms[]
images[]
links[]
body
Page 37
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 37
© Copyright 2008, Bryan Basham
Document Example<html><head></head><body> <div id="login"> <form action="" id="Login_form"> <fieldset> <ol> <li> <label for="login_id"> Login <abbr title="identification">ID</abbr> </label> <input id="login_id" name="username" type="text" /> </li> <li> <label for="password">Password</label> <input id="password" name="userpass" type="password" /> <a href="#">go</a> </li> </ol> </fieldset> </form> </div></body></html>
Page 38
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 38
© Copyright 2008, Bryan Basham
Document Example Model
<HTML>
<HEAD> <BODY>
<DIV>
<FORM>
<OL>
<LI>
<FIELDSET>
<LABEL> <A><LABEL>
<LI>
<INPUT “username”> <INPUT “userpass”>
Page 39
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 39
© Copyright 2008, Bryan Basham
Forms
Form objects provide quick access to form elements
Login_form:Form
login_id:Input
type=textname=usernamevalue=b_basham
password:Input
type=textname=userpassvalue=MySecret
:Fieldset
elements
Page 40
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 40
© Copyright 2008, Bryan Basham
Document Object Model
DOM Level 0
de-facto standard for pre-XHTML
DOM Level 1
DOM navigation and manipulation
DOM Level 2
XML namespace-aware
events
DOM Level 3 (in progress)
Page 41
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 41
© Copyright 2008, Bryan Basham
Documents contain Elements which might contain a sequence of text and/or other elements.
DOM Type Hierarchy
Node
Document Element CharacterData
Text Comment
CDATASection
1
childNodes
parentNode 1
0..*
0..*
The relationship between the Element andthe abstract CharacterData type is implied bythe Node's ability to contain children of anyNode subtype, such as Text or Comment.
documentElementAKA: the root node
Page 42
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 42
© Copyright 2008, Bryan Basham
Node is an abstraction for traversing and modifying a tree structure.
Node Interface
«CORBA Interface»
Node
nodeName : DOMStringnodeValue : DOMStringnodeType : int {enum of types}firstChild : NodelastChild : NodepreviousSibling : NodenextSibling : Node
insertBeforereplaceChildremoveChildappendChildhasChildNodes() : boolean
1
0..*
childNodes
parentNode
Page 43
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 43
© Copyright 2008, Bryan Basham
A Document contains a single root Element
An Element can contain any number of subnodes: usually text and other elements.
Document Interface
«CORBA Interface»
Document
doctype : DocumentTypeimplementation : DOMImplementationdocumentElement : Element
createElement(tagName) : ElementcreateTextNode(data) : TextcreateCDATASection(data) : CDATASectiongetElementsByTagName(tagName) : NodeListgetElementById(elementId) : Element
«CORBA Interface»
Element
tagName : DOMString
hasAttribute(attrName) : booleangetAttribute(attrName) : DOMStringsetAttribute(attrName, attrValue)removeAttribute(attrName)getElementsByTagName(tagName) : NodeList
«CORBA Interface»
Node
1
documentElementAKA: the root node
Page 44
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 44
© Copyright 2008, Bryan Basham
Node Example
LI:Element
LABEL:Element INPUT:Element A:Element
"password":Text "go":Text
parentNodefir
stChild
lastC
hildnextSibling
previousSibling
<li> <label for="password">Password</label> <input id="password" name="userpass" type="password" /> <a href="#">go</a></li>
Page 45
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 45
© Copyright 2008, Bryan Basham
Node Example (reality check)<li> <label for="password">Password</label> <input id="password" name="userpass" type="password" /> <a href="#">go</a></li>
LI:Element
LABEL:Element INPUT:Element A:Element
"Password":Text "go":Text
firstChild lastChild
ws:Text ws:Text ws:Text ws:Text
Page 46
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 46
© Copyright 2008, Bryan Basham
The Event Model(s)
Traditional (AKA Level 0)
event handlers as tag attributes (onclick)
event handlers set as Element properties
No event model in DOM Level 1
Standard event model in DOM Level 2
event listeners are registered with the element
Page 47
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 47
© Copyright 2008, Bryan Basham
Event Types
Mouse:
click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout
Keyboard:
keypress, keydown, keyup
Window:
load, unload, resize, scroll, abort, error
Form:
focus, blur, select, change, reset, submit
Page 48
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 48
© Copyright 2008, Bryan Basham
Event Propagation
Netscape Model
Element1
Element2
Event Bubbling
Element1
Element2
Event Capturing
Microsoft Model
Page 49
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 49
© Copyright 2008, Bryan Basham
Traditional Event Model
Assign handler on tag attribute<a href=”#” onclick=”return LoginScreen.validateForm();”>go</a>
Assign handler with element propertyvar goButton = document.getElementById('goButton');goButton.onclick = function(event) { return
LoginScreen.validateForm(); };
CONS:
Limited to only one handler per element and event type
Poor separation of concerns: behavior mixed in with structure
Inconsistent event propagation
Page 50
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 50
© Copyright 2008, Bryan Basham
DOM Level 2 Events
HTML elements are event targets:
«CORBA Interface»
EventTarget
addEventListener(listener)removeEventListener(listener)dispatchEvent(event)
«CORBA Interface»
EventListener
handleEvent(event)
0..*
«CORBA Interface»
Event
type : DOMString
target : EventTarget {an element}currentTarget : EventTargeteventPhase : EventPhaseEnumtimeStamp : DOMTimeStamp
stopPropagation() : voidpreventDefault() : void
EventPhaseEnum
CAPTURING_PHASE = 1AT_TARGET = 2BUBBLING_PHASE = 3
Page 51
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 51
© Copyright 2008, Bryan Basham
Standard Event Propagation
The standard propagation model is a combination of the proprietary models:
Element1
Element2
CAPTU
RE_PH
ASE
BU
BBLIN
G_PH
ASE
AT_TARGET
Page 52
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 52
© Copyright 2008, Bryan Basham
Event Registration (HTML)<body onload="EventsLevel2.registerHandlers(false);">
<h1>Event Model: Level 2 w/ No Capturing</h1>
<div id="outerBox"> Element1
<div id="innerBox">
Element2 </div>
</div>
</body>
Page 53
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 53
© Copyright 2008, Bryan Basham
Event Registration (JS)// Create the EventsLevel2 namespace var EventsLevel2 = {
handleEvent : function(event) {
var div = event.currentTarget; console.info("Current target: " + div.id
+ " had event: " + event
+ " in phase: " + event.eventPhase);
var propagate = confirm("Click OK to propagate the event.");
if ( ! propagate ) event.stopPropagation();
},
registerHandlers: function(capture) {
var outerBox = document.getElementById('outerBox');
var innerBox = document.getElementById('innerBox'); outerBox.addEventListener("click", EventsLevel2, capture);
innerBox.addEventListener("click", EventsLevel2, capture);
},
} // END of EventsLevel2 namespace definition
Page 54
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 54
© Copyright 2008, Bryan Basham
Timed Events Example
The Window object includes methods to setup periodic activities.
For example, a clock:
Page 55
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 55
© Copyright 2008, Bryan Basham
Timing with setInterval
var Clock = {
displayTime : function(event) { var time = // calculate the time string from new Date()
var clockBox = document.getElementById('clockBox');
clockBox.innerHTML = time;
}, toggleActivation : function() {
Clock.ACTIVE = ! Clock.ACTIVE;
if ( Clock.ACTIVE ) {
Clock.INTERVAL_ID = setInterval(Clock.displayTime, 1000); document.getElementById('actButton').value = "Stop Clock";
} else {
clearInterval(Clock.INTERVAL_ID); document.getElementById('actButton').value = "Start Clock";
}
},
ACTIVE : false, INTERVAL_ID : 0,
} // END of Clock namespace definition
Page 56
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 56
© Copyright 2008, Bryan Basham
Timing with setTimeoutvar Clock = {
displayTime : function(event) {
var time = // calculate the time string from new Date()
var clockBox = document.getElementById('clockBox'); clockBox.innerHTML = time;
Clock.TIMEOUT_ID = setTimeout('Clock.displayTime()', 1000);
}, toggleActivation : function() {
Clock.ACTIVE = ! Clock.ACTIVE;
if ( Clock.ACTIVE ) {
Clock.TIMEOUT_ID = setTimeout('Clock.displayTime()', 1000); document.getElementById('actButton').value = "Stop Clock";
} else {
clearTimeout(Clock.INTERVAL_ID);
document.getElementById('actButton').value = "Start Clock"; }
},
ACTIVE : false, TIMEOUT_ID : 0,
} // END of Clock namespace definition
Page 57
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 57
© Copyright 2008, Bryan Basham
Ajax
Asynchronous JavaScript and XML
perform HTTP requests without a page refresh
responses are small chunks of data or content
use DOM scripting to modify the current page
User or timed events can trigger JS code to invoke an HTTP request
The XMLHttpRequest class is not yet a
standard
Page 58
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 58
© Copyright 2008, Bryan Basham
Creating an Ajax requestvar MyAjax = { createRequest : function() {
var request;
try {
request = new XMLHttpRequest(); } catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) { console.error(failed);
request = null;
}
} }
return request;
},} // END of MyAjax namespace definition
Page 59
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 59
© Copyright 2008, Bryan Basham
Handling an Ajax requestvar MyAjax = {
createRequest : {}, // from previous slide
sendRequest : function(url, requestData, callbackFunction) { var request = MyAjax.createRequest();
request.open("POST", url, true);
request.setRequestHeader("Content-Type", "application/x-javascript;");
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
if (request.responseText) { callbackFunction(request.responseText);
}
}
}; request.send(JSON.stringify(requestData));
},
} // END of MyAjax namespace definition
Page 60
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 60
© Copyright 2008, Bryan Basham
Topics Mind Map
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 61
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 61
© Copyright 2008, Bryan Basham
JavaScript Frameworks
Even with the DOM and Level 0 APIs, client-side JavaScript is rather primitive.
Browsers have differing level of support for client-side APIs and bugs.
Many groups have built frameworks to:
smooth out the bugs
build higher level APIs
create UI widgets
Page 62
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 62
© Copyright 2008, Bryan Basham
Prototype...
is a framework that provides low-level tools that extend basic JavaScript
creates work-arounds for browser bugs
provides APIs for higher-level programming
selecting DOM elements
better DOM traversal and manipulation
more functional programming
easier Ajax
more flexible event processing
Page 63
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 63
© Copyright 2008, Bryan Basham
Element Selectors
The $ function selects an HTML element by its id
$('myID') === document.getElementById('myID')
$('id1', 'id2') === [ $('id1'), $('id2') ]
The $$ function selects a collection of HTML
elements
$$('li') === document.getElementsByTagName('li')
$$('#myID') === [ $('myID') ]
$$('div.MyCssClass') ==> array of DIV elements with the MyCssClass class
$$('ol#section2 > li') ==> array of LI elements within the OL element named 'section2'
and many more selection constructs; most are based on CSS selectors
Page 64
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 64
© Copyright 2008, Bryan Basham
DOM Enhancements
The $ and $$ functions returns DOM
elements but with additional methods
Visibility: hide, show, toggle, visible
Element class: addClassName, removeClassName,
toggleClassName, hasClassName
Style: getStyle, setStyle
Attributes: readAttribute, writeAttribute
Page 65
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 65
© Copyright 2008, Bryan Basham
DOM Enhancements
Navigation
Basic: up, down, next, previous
Up/Down: ancestors, descendants, immediateDescendants
Across: siblings, nextSibling, previousSibling
ignores text nodes
Manipulation: update, replace, insert, remove, wrap
Page 66
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 66
© Copyright 2008, Bryan Basham
Functional Programming
List processing: each, map, pluck
Searching: detect, select, reject, partition
Sorting: sortBy, min, max
Other “Enumerable” objects:
$A() creates an Enumerable array
$H() creates an Enumerable hash map
$R(min, max) creates an Enumerable numeric range
Page 67
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 67
© Copyright 2008, Bryan Basham
Easier Ajax
Raw Ajax processing is cumbersome
The Request class provides higher-level APInew Ajax.Request('getData.jsp', { method: 'get', onComplete: function() { /* handle response data */ }
});
The Updater provides element modificationnew Ajax.Updater('myElement', 'getHtmlChunk.jsp', { method: 'get' });
The PeriodicalUpdater updates on an interval
Page 68
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 68
© Copyright 2008, Bryan Basham
Easier Event Handling
Two distinct event models (pre- and post-DOM) is troublesome
Observing$('testButton').observe('click', MyScreen.handler1);
$('testButton').observe('click', MyScreen.handler2);
DOM loadingEvent.observe(window, 'load', MyScreen.initialize);
Before the <body onload=''> handler
...but after DOM has completely loaded
Prototype supports custom event handling
Page 69
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 69
© Copyright 2008, Bryan Basham
script.aculo.us...
is a framework that provides high-level tools that extend widgets functionality
is built on top of Prototype
provides APIs for widget programming
effects
drag-and-drop
widgets: in-place editing, auto-completer, slider
sound APIs
additional DOM building APIs
Page 70
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 70
© Copyright 2008, Bryan Basham
Effects
Effects perform element animation
to show motion
to alert user to new content
to show user what has changed
Core: Effect.Morph / Effect.Move /
Effect.ScrollTo / Effect.Scale / Effect.Highlight
Hiding: Effect.Fade / Effect.BlindDown /
Effect.SlideDown
Showing: Effect.Appear / Effect.BlindUp /
Effect.SlideUp
Page 71
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 71
© Copyright 2008, Bryan Basham
Drag and Drop
Making draggables:new Draggable('myElement', options);
Making droppables:Droppables.add('myElement', options);
SortableSortable.create('myElement', options);
Page 72
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 72
© Copyright 2008, Bryan Basham
Topics Mind Map
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 73
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 73
© Copyright 2008, Bryan Basham
Other JS tools
jQuery is an alternate to Prototype and script.aculo.us
Other UI widget sets:
Google Web Toolkit (GWT)
ExtJS
YahooUI Library
DOJO
Lots of other libraries (click here)
Page 74
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 74
© Copyright 2008, Bryan Basham
Topics Mind Map
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 75
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 75
© Copyright 2008, Bryan Basham
Building JS Components
Build classes to represent data on the client-side
Build classes for client-side UI widgets; possibly in conjunction with JSF
Build namespaces for screen-specific functionality
event handlers
timed event handlers
Ajax handlers
Page 76
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 76
© Copyright 2008, Bryan Basham
Example / Demo
Page 77
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 77
© Copyright 2008, Bryan Basham
Q & A
Introduction
Prototype& Scriptaculous
LanguageFundamentals
Client-sideAPIs
Other tools
Roll Your Own
JavaScriptWizard
Page 78
Colorado Software Summit: October 19 – 24, 2008
Bryan Basham — Becoming a JavaScript Wizard Slide 78
© Copyright 2008, Bryan Basham
Resources
Head First JavaScript (O'Reilly)
JavaScript – The Definitive Edition (O'Reilly)
DOM Scripting (friends of ed)
Practical Prototype and script.aculo.us (Apress)
designing with web standards, 2nd ed. (New Riders)
Mozilla: site
ECMAScript standard: site and PDF
Douglas Crawford's site and lectures
JSON
Prototype
script.aculo.us
Others: jQuery, ExtJS, YUI, GWT, Dojo, and so many more