KEMBAR78
Intro to-javascript | PDF
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 1
© Copyright 2012, Software Alchemy
Introduction to JavaScript
Bryan Basham
Software Alchemy
basham47@gmail.com
http://www.linkedin.com/in/SoftwareAlchemist
Intro
Introduction
to JavaScript
Functional
Programming
Language
OO
Programming
DOM APIs
Event
Model
Odds & Ends
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 2
© Copyright 2012, Software Alchemy
Introduction
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
Functional
Programming
Language
OO
Programming
DOM APIs
Event
Model
Odds & Ends
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 3
© Copyright 2012, Software Alchemy
Web Standards
● Supported by most browsers and mobile
devices
● So what?
– Abundant skilled developers
● Who cares?
– Better accessibility and usability
– Good tools
– “Write once, publish everywhere”
● :-) well almost, of course there is always IE
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 4
© Copyright 2012, Software Alchemy
Example Page
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 5
© Copyright 2012, Software Alchemy
Separation of Concerns
● What to separate?
– Structure
– Presentation (aka style)
– Behavior
● Unobtrusive JavaScript
● So what?
– Clarity of code
– Easy to modify and replace look and feel (LnF)
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 6
© Copyright 2012, Software Alchemy
Structure
● XHTML (or HTML v5)
● 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>
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 7
© Copyright 2012, Software Alchemy
Presentation
● Cascading Style Sheets (CSS)
● 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;
}
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 8
© Copyright 2012, Software Alchemy
Behavior
● JavaScript (aka ECMAScript 262)
● Rich object-based and functional language
● Web behavior:
– manipulate the page structure (DOM scripting)
– handle user-generated events on elements
– handle sync & async communication with server
● CONS:
– some inconsistencies between browsers
● did I mention IE?
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 9
© Copyright 2012, Software Alchemy
Why is this important?
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
Client
Server
UI Code
Data
Behavior
StructureStructure
Presentation
Behavior
Data
conversion
invoke
select next view
generate
enhance
style / layout
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 10
© Copyright 2012, Software Alchemy
Language Fundamentals
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
Functional
Programming
OO
Programming
DOM APIs
Event
Model
Odds & Ends
symbols
syntax
JSON
data types
Language
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 11
© Copyright 2012, Software Alchemy
Symbols
● Symbols are similar to identifiers in Java
● Symbols can hold:
– Data
var name = “Bryan”;
var age = 47;
– Objects
var obj = {};
– Functions
function add(a, b) { return a + b; }
● Symbols are also used as keys in object
hashes:
{ name: “Bryan”, age: 47 }
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 12
© Copyright 2012, Software Alchemy
Scope Rules
● Global scope
<script>
var G1 = 42;
</script>
● Local scope
function f() {
var L1 = 47;
return L1 + G1;
}
f() ==> 89
function g() {
var L2 = 420; // this has local scope
function h() { // local function
var L2 = 42; // nested scoping
return L2;
}
return L2 + h();
}
g() ==> 462
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 13
© Copyright 2012, Software Alchemy
Namespaces
● Globals (vars and functions) create clutter
● Namespace is a 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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 14
© Copyright 2012, Software Alchemy
Mimicking Java Packages
● You can nest namespaces to mimic packages:
var INow = {
utils : {},
domain : {},
screens : {}
};
● Then put functions, classes, etc in packages:
INow.utils.map = function(array, funct) { ... };
INow.domain.Person = function() { /* class constructor */ };
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 15
© Copyright 2012, Software Alchemy
Data Types
● Numbers (64-bit floating point)
42 * 10.0 ==> 420
typeof 42 ==> “number”
typeof 4.2 ==> “number”
42 / “10” ==> 4.2
● Strings (Unicode, ' and “ delimited)
“foo”
'she said “he said”'
'isn''t great!'
typeof “foo” ==> “string”
42 + “10” ==> “4210”
● Booleans (true and false)
typeof true ==> “boolean”
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 16
© Copyright 2012, Software Alchemy
More Data Types
● Dates
var now = new Date();
var DoB = new Date(1964, 6, 22); // new Date(YYYY, MM, DD, h, m, s, ms)
var ts = Date.parse(timestampString);
now.getTime() // milliseconds since epoch
// and so on (lots of methods)
● Regular expressions
var re = new RegExp(“(d{2})W(d{2})W(d{4})”, “g”); // 07-22-1964
var re = /(d{2})W(d{2})W(d{4})/g;
var re = new RegExp();
re.compile(“(d{2})W(d{2})W(d{4})”, “g”);
– Modeled after Perl 5 syntax
– Supports capture groups
– Supports multi-line
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 17
© Copyright 2012, Software Alchemy
Even More Data Types
● Arrays
● Objects
● Functions
● Error (and subclasses)
● Special objects: Math and JSON
● null
typeof null ==> “object”
● undefined
typeof undefined ==> “undefined”
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 18
© Copyright 2012, Software Alchemy
Arrays
● Syntax
var myArray = [13, 42, 47, 420];
● Access
myArray.length ==> 4
myArray[1] ==> 42
myArray[3] ==> 420
myArray[3] = 120;
myArray[3] ==> 120
● Iteration
for ( var i=0; i<myArray.length; i++ ) {
console.info(“myArray[“ + i + “] is “ + myArray[i]);
}
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 19
© Copyright 2012, Software Alchemy
Syntax Overview
● Based upon Java syntax for:
– Literals, expressions and operators
– Declarations:
● Loosely-typed variables
● Functions
– Statements
● But not:
– Type structures: classes nor interfaces
– Concurrency constructs: JS is single-threaded
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 20
© Copyright 2012, Software Alchemy
Special Operators
● Equality operator (==) vs Identify op (===)
42 == new Number(42) ==> true
42 == “42” ==> true
42 === new Number(42) ==> false
42 === “42” ==> false
● The typeof operator returns a type name
typeof (42) ==> “number”
typeof [42, 47] ==> “object” // WTF?
typeof { foo:42 } ==> “object”
– Complete list: boolean, number, string,
function, undefined, and object
● The void operator always returns undefined
void( /* some calculation */ ) ==> undefined
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 21
© Copyright 2012, Software Alchemy
Special Operators
● The delete operator removes an object entry
var obj = { foo: 47, bar: 42 };
obj.foo ==> 47
delete obj.foo ==> true
obj.foo ==> undefined
● The in operator
'foo' in obj ==> true
● The get and set operators (but... not in IE)
var obj = { get foo() { return 47; },
set bar(v) { this._bar = v; },
get bar() { return “Hello ” + this._bar; } };
obj.foo ==> 47
obj.foo = 42; // but no change to obj
obj.bar = “Bryan”;
obj.bar ==> “Hello Bryan”
obj._bar ==> “Bryan”
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 22
© Copyright 2012, Software Alchemy
Special Statements
● The for-in statement
for ( var prop in obj ) {
console.info(“prop '%s' is %o”, prop, obj[prop]);
} ==>
prop 'foo' is 47
prop 'bar' is “Hello Bryan”
prop '_bar' is “Bryan”
– Warning: more in an object than meets the eye
● The with statement
with (obj) {
console.info(“obj.foo is %d”, foo);
bar = “Fred”;
}
obj.bar ==> “Hello Fred”
– Warning: this statement is tricky to use properly
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 23
© Copyright 2012, Software Alchemy
Special functions
● The eval function
eval(“2 * 3”) ==> 6
– Warning: use with caution
● The call function
function addUp() {
var sum = 0;
for ( var i=0; i < arguments.length; i++ ) sum += arguments[i];
return sum;
}
addUp.call(null, 1, 2, 3, 4, 5); ==> 15
● The apply function
addUp.apply(null, [1, 2, 3, 4, 5]); ==> 15
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 24
© Copyright 2012, Software Alchemy
JavaScript Object Notation
● JSON, created by Douglas Crawford, is a
string notation for JS objects
– Just a subset; doesn't include functions
– Native support in ECMAScript v4+
– May require a library, json.js, for old browsers
– Don't use built-in eval function
● Used mostly to pass data between browsers
and servers
● Put also becoming popular in other contexts,
such as NoSQL data stores
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 25
© Copyright 2012, Software Alchemy
Native Support
● ECMAScript v4 defines the JSON object
● Generate JSON strings this way:
var obj = { name: "Bryan", age: 47 }
var str = JSON.stringify(obj) ==> "{"name":"Bryan","age":47}"
● Parse JSON strings this way:
var obj2 = JSON.parse(str)
obj2.name ==> "Bryan"
obj2.age ==> 47
obj == obj2 ==> false
● Works in: IE8+, FF3.1+, Safari 4+, Chrome 3+,
and Opera 10.5
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 26
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
DOM APIs
Event
Model
Odds & Ends
symbols
syntax
JSON
data types
Language
syntax
encapsulation
ctor prototype
core
JSON
revisited
hybrid OO
no-class
OO
Programming
Functional
Programming
Object-Oriented Programming
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 27
© Copyright 2012, Software Alchemy
Object Creation
● Creating an object
var O1 = new Object();
O1.a = 47;
O1.method = function() { console.info(this.a); };
typeof O1 ==> "object"
● OR as a literal
var O1 = {
A : 47,
method : function() { console.info(this.a); }
}
● Remember “namespaces”? Just objects
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 28
© Copyright 2012, Software Alchemy
Object Property Access
● Access object attributes
O1.a ==> 47
O1.a = 42;
O1.method() ==> displays '42' in the console
● Objects can also be treated as associative
arrays (aka hash maps)
O1["a"] ==> 42
O1["a"] = 420;
O1["method"]() ==> displays '420' in the console
var prop = “a”;
O1[prop] ==> 42
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 29
© Copyright 2012, Software Alchemy
JavaScript Core Classes
● Built-in
– Object
– Date
– RegExp
– Error (and subclasses)
● Wrappers
– String, Number and Boolean
● Odd balls
– Function and Array
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 30
© Copyright 2012, Software Alchemy
But wait... no classes
● You can't create classes in JavaScript
class Range { /* code here */ } // NO SUCH SYNTAX
● You can only create object constructors
typeof Date ==> "function"
var Range = function(start, end) {
this.start = start;
this.end = end;
}
var r1 = new Range(42, 47);
r1.start ==> 42
r1.end ==> 47
var r2 = new Range(13, 420);
r2.start ==> 13
r2.end ==> 420
r1 #111:Range
start = 42
end = 47
r2 #222:Range
start = 1
end = 10
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 31
© Copyright 2012, Software Alchemy
Encapsulation
● Ugh.. these attributes are public
r2.start = 520;
r2.start ==> 520 // Semantics broken: the “start” is after the “end”
● Closures allow us to hide private data
var Range = function(start, end) {
this.getStart = function() { return start; }
this.getEnd = function() { return end; }
}
var r1 = new Range(42, 47);
r1.start ==> undefined
r1.getStart() ==> 42
r1.getEnd() ==> 47
var r2 = new Range(13, 420);
r2.getStart() ==> 13
r2.getEnd() ==> 420
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 32
© Copyright 2012, Software Alchemy
Encapsulation Object Model
r1 #111:Range
getStart
getEnd
#987:CallObj
start = 42
end = 47
#876:CallObj
start = 13
end = 420
function() { return start; }
function() { return end; }
r2 #222:Range
getStart
getEnd
function() { return start; }
function() { return end; }
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 33
© Copyright 2012, Software Alchemy
Encapsulation (2)
● Creating setters
var Range = function(start, end) {
this.getStart = function() { return start; }
this.setStart = function(x) {
if ( x <= end ) {
start = x;
} else {
throw new Error(“illegal value”);
}
}
this.getEnd = function() { return end; }
this.setEnd = function(x) { /* like above */ }
}
var r = new Range(42, 47);
r.getStart() ==> 42
r.setStart(13)
r.getStart() ==> 13
r.setStart(50) // throws an Error
r.getStart() ==> 13
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 34
© Copyright 2012, Software Alchemy
But... this too has problems
● This pattern creates lots of object-specific
functions
r1 #111:Range
getStart
setStart
getEnd
setEnd
#222:Range
getStart
setStart
getEnd
setEnd
function() {...}
function(x) {...}
function() {...}
function(x) {...}
function() {...}
function(x) {...}
function() {...}
function(x) {...}
r2
#987:CallObj
start = 42
end = 47
#876:CallObj
start = 13
end = 420
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 35
© Copyright 2012, Software Alchemy
Another Class-like Idiom
● Constructors have prototypes
var Range = function(st, en) {
this.start = st;
this.end = en;
}
// Setup shared Range object methods
Range.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 objects
var 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);
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 36
© Copyright 2012, Software Alchemy
Another Class-like Idiom
● Function are reused across all objects
Range.prototype
getStart
setStart
getEnd
setEnd
function() {...}
function(x) {...}
function() {...}
function(x) {...}
r1 #111:Range
start = 42
end = 47
r2 #222:Range
start = 13
end = 420
r3 #333:Range
start = 1.2
end = 3.14
r4 #444:Range
start = 1
end = 10
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 37
© Copyright 2012, Software Alchemy
Hybrid OO Idiom
var Circle = function(radius) {
// Create privileged methods
this.getRadius = function () { return radius; }
}
// Create public, but non-privileged methods
Circle.prototype.getDiameter
= function() { return this.getRadius() * 2; }
Circle.prototype.getArea
= function() { return Circle.PI * this.getRadius() * this.getRadius();
}
// Create class constants
Circle.PI = 3.14159;
var c1 = new Circle(4.2);
c1.getRadius() ==> 4.2
c1.getDiameter() ==> 8.4
c1.getArea() ==> 55.4176476
var c2 = new Circle(10);
c1.getRadius() ==> 10
c1.getDiameter() ==> 20
c1.getArea() ==> 314.159
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 38
© Copyright 2012, Software Alchemy
Object model of hybrid OO
Circle.prototype
getDiameter
getArea
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; }
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 39
© Copyright 2012, Software Alchemy
Advanced Class Features
● Admittedly these “class-like” programming
idioms are awkward
● Mimicking class inheritance is even more
complex
● They have their place (simple domain model)
● There are other, more advanced, inheritance
mechanisms
– Such as “prototypal inheritance”
– See Douglas Crawford on Resource slide at end
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 40
© Copyright 2012, Software Alchemy
JSON Revisited
● 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);
● But what about our objects?
var c1 = new Circle(4.2);
var c1Str = JSON.stringify(c1); // "{}" WTF?!?! Where's my object?
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 41
© Copyright 2012, Software Alchemy
Hybrid-Class JSON Methods
// Create the Circle class constructor
function Circle(radius) { ... };
// 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);
c.getArea() ==> 5541.76476
var cStr = JSON.stringify(c);
var newC = JSON.parse(cStr, MyJSON.classReviver);
newC.getArea() ==> 5541.76476
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 42
© Copyright 2012, Software Alchemy
JSON for Circle
● The Circle instance method toJSON preforms
conversion from object to string.
var c1 = new Circle(42);
c1.getArea(); // 5541.76476
var c1Str = JSON.stringify(obj); // '""Circle(42)""'
● The JSON.parse method uses my 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.
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 43
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
DOM APIs
Event
Model
Odds & Ends
symbols
syntax
JSON
data types
Language
syntax
encapsulation
ctor prototype
core
JSON
revisited
hybrid OO
no-class
OO
Programming
collection
functions
closures
1st
class
Ajax event
handlers
Functional
Programming
Functional Programming
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 44
© Copyright 2012, Software Alchemy
Function Creation
● Definition syntax
function square(x) { return x * x; }
square(12) ==> 144
typeof square ==> “function”
● OR as a variable
var square = function(x) { return x * x; }; // lambda function (Lisp)
square(12) ==> 144
● OR as an object
var square = new Function(“x”, “return x * x;”);
square(12) ==> 144
● ...these are all the same
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 45
© Copyright 2012, Software Alchemy
Invoking Functions
● Imagine the function:
function add(a, b, c, d) {
c = (c != undefined) ? c : 0;
d = (d != undefined) ? d : 0;
return a + b + c + d;
}
● Don't have to give all arguments:
add(1, 2) ==> 3
add(1, 2, 3) ==> 6
add(1, 2, 3, 4) ==> 10
● Too many arguments are ignored:
add(1, 2, 3, 4, 5, 6, 7) ==> 10
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 46
© Copyright 2012, Software Alchemy
Accessing Function Arguments
● You can create a function that takes any
number of arguments:
function addAll() {
var sum = 0;
for ( var idx=0; idx<arguments.length; idx++ ) {
sum += arguments[idx];
}
return sum;
}
add(1, 2) ==> 3
add(1, 2, 3) ==> 6
add(1, 2, 3, 4) ==> 10
add(1, 2, 3, 4, 5) ==> 15
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 47
© Copyright 2012, Software Alchemy
1st
Class Citizens
● Can store functions in variables
● Can store functions in objects
– Like we did with privileged methods in the hybrid
class idiom defined in the constructor function
● Can return functions from other functions
● Can pass functions in as arguments
function isOdd(n) { return (n % 2) == 1; }
function not(predicate) {
return function(x) { return ! predicate(x); };
}
var isEven = not(isOdd);
isEven(2) ==> true
isEven(5) ==> false
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 48
© Copyright 2012, Software Alchemy
Collections
● Example 1:
function map(array, funct) {
var newArray = new Array();
for ( var i=0; i<array.length; i++ ) {
newArray[i] = funct(array[i]);
}
return newArray;
}
// Run unit tests
function square(x) { return x * x; }
var myArray = [13, 42, 47];
map( myArray, square ); ==> [169, 1764, 2209]
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 49
© Copyright 2012, Software Alchemy
Collections
● Example 2:
function find(array, pred) {
for ( var i=0; i<array.length; i++ ) {
var value = array[i];
if ( pred(value) ) return value;
}
}
// Run unit tests
function isOdd(n) { return (n % 2) == 1; }
var myArray = [13, 42, 47];
function isShort(s) { return s.length <= 3; }
var myStrings = [“the”, “quick”, “brown”, “fox”];
find( myArray, isOdd ); ==> 13
find( myStrings, not(isShort) ); ==> “quick”
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 50
© Copyright 2012, Software Alchemy
Collections
● Example 3:
function gather(array, pred) {
var newArray = [];
for ( var i=0; i<array.length; i++ ) {
var value = array[i];
if ( pred(value) ) newArray.push(value);
}
return newArray;
}
// Run unit tests
function isOdd(n) { return (n % 2) == 1; }
var myArray = [13, 42, 47];
function isShort(s) { return s.length <= 3; }
var myStrings = [“the”, “quick”, “brown”, “fox”];
gather( myArray, isOdd ); ==> [13, 47]
gather( myStrings, not(isShort) ); ==> [“quick”, “brown”]
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 51
© Copyright 2012, Software Alchemy
Closures
● Closures hold state within a function
function makeCutoffFunction(nTimes, funct) {
return function(x) { // creating a new function object
nTimes--; // access to local state variable
if ( nTimes >= 0 ) {
return funct(x); // execute the function
}
};
}
var squareOnce = makeCutoffFunction( 1, square );
squareOnce(12) ==> 144
squareOnce(13) ==> void
var logThrice = makeCutoffFunction( 3, console.info );
logThrice("first log message"); // log once
logThrice("second log message"); // log twice
logThrice("third log message"); // log thrice
logThrice("fourth log message"); // stops logging
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 52
© Copyright 2012, Software Alchemy
Event Handlers
● Example:
<button onclick=”this.className = 'red'”> Click me </button>
● Script is treated as a function:
var buttonClickFunction = function() { this.className = 'red'; }
● Applied to the element object when clicked:
buttonClickFunction.apply(buttonElement)
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 53
© Copyright 2012, Software Alchemy
Ajax
● Asynchronous JavaScript and XML
– Perform HTTP requests without a page refresh
– Responses area 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 becoming a
standard
– See: http://www.w3.org/TR/XMLHttpRequest/
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 54
© Copyright 2012, Software Alchemy
Creating an Ajax Request
var 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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 55
© Copyright 2012, Software Alchemy
Sending an Ajax Request
var MyAjax = {
createRequest : function() {}, // from previous slide
sendRequest : function(url, requestData, callbackFunction) {
var request = MyAjax.createRequest();
request.open("POST", url, true);
request.setRequestHeader("Content-Type", "application/json");
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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 56
© Copyright 2012, Software Alchemy
Ajax Example
● Click on the button and JS requests the list of
definitions from the server:
● Here's what the HTTP request looks like in
Firebug:
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 57
© Copyright 2012, Software Alchemy
Ajax Example
● Populate a definition list when clicking a button
<button onclick="Screen.buttonHandler()">Click me</button>
<dl id="definitions"></dl>
var Screen = {
buttonHandler : function() {
MyAjax.sendRequest("/TestJS/lesson/ajaxDefinitions",
null, Screen.populateDefinitions);
},
populateDefinitions : function(responseText) {
var definitions = JSON.parse(responseText);
var defList = document.getElementById('definitions');
each(definitions, function (def) {
var dt = document.createElement('dt');
dt.innerHTML = def.name;
defList.appendChild(dt);
var dd = document.createElement('dd');
dd.innerHTML = def.definition;
defList.appendChild(dd);
});
}
}
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 58
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
DOM APIs
Event
Model
Odds & Ends
symbols
syntax
JSON
data types
Language
DOM
window
document
query
traversal
manipulation
DOM APIs
collection
functions
closures
1st
class
Ajax event
handlers
Functional
Programming
syntax
encapsulation
ctor prototype
core
JSON
revisited
hybrid OO
no-class
OO
Programming
DOM APIs
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 59
© Copyright 2012, Software Alchemy
Window
● The window object is the “global object”
● Control methods: close, focus, blur, move,
open, print and resize
window
navigator
frames[]
location
history
document
screen
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 60
© Copyright 2012, Software Alchemy
Document
● The document object represents the structure
of the current web page
● Provides easy access to critical elements
document
anchors[]
applets[]
forms[]
images[]
links[]
body
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 61
© Copyright 2012, Software Alchemy
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>
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 62
© Copyright 2012, Software Alchemy
Document Example Model
<HTML>
<HEAD> <BODY>
<DIV>
<FORM>
<OL>
<LI>
<FIELDSET>
<LABEL>
<LI>
<INPUT “username”> <LABEL> <A><INPUT “userpass”>
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 63
© Copyright 2012, Software Alchemy
Node
Document Element CharacterData
Text Comment
CDATASection
1
childNodes
parentNode 1
0..*
0..*
The relationship between the Element and
the abstract CharacterData type is implied by
the Node's ability to contain children of any
Node subtype, such as Text or Comment.
documentElement
{AKA: the root node}
DOM Type Hierarchy (partial)
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 64
© Copyright 2012, Software Alchemy
DOM Traversal API
● The Node provides the traversal access:
Node
parentNode : Node
childNodes : NodeList
firstChild : Node
lastChild : Node
previousSibling : Node
nextSibling : Node
hasChildNodes() : boolean
1
0..*
childNodes
parentNode
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 65
© Copyright 2012, Software Alchemy
Traversal Example
LI:Element
LABEL:Element INPUT:Element A:Element
"password":Text "go":Text
parentNode
firstChild
lastChild
nextSibling
previousSibling
<li>
<label for="password">Password</label>
<input id="password" name="userpass" type="password" />
<a href="#">go</a>
</li>
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 66
© Copyright 2012, Software Alchemy
Traversal 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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 67
© Copyright 2012, Software Alchemy
DOM Query APIs
Document
getElementsByTagName(tagName) : NodeList
getElementById(elementId) : Element
Element
tagName : DOMString
getElementsByTagName(tagName) : NodeList
getElementsByClassName(clsName) : NodeList
Node
1
documentElement
{AKA: the root node}
NodeList
length : long
[idx] : Node
item(idx) : Node
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 68
© Copyright 2012, Software Alchemy
Query the DOM
● Find an element by its id
// retrieves all form input elements
var myForm = document.getElementById('loginForm')
● Find a list of elements by tag type
// retrieves all <input> elements in the whole document
document.getElementsByTagName('input')
// retrieves all <input> elements in the <form id='loginForm'>...</form>
myForm.getElementsByTagName('input')
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 69
© Copyright 2012, Software Alchemy
DOM Manipulation
Document
createElement(tagName) : Element
createTextNode(data) : Text
createCDATASection(data) : CDATASection
Element
tagName : DOMString
hasAttribute(attrName) : boolean
getAttribute(attrName) : DOMString
setAttribute(attrName, attrValue)
removeAttribute(attrName)
1
documentElement
{AKA: the root node}
Node
insertBefore
replaceChild
removeChild
appendChild
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 70
© Copyright 2012, Software Alchemy
Manipulation Example
● From the Ajax example: start with empty <dl>
<dl id="definitions"></dl>
● Ajax callback fills in the list
var defList = document.getElementById('definitions');
each(definitions, function (def) {
var dt = document.createElement('dt');
dt.innerHTML = def.name;
defList.appendChild(dt);
var dd = document.createElement('dd');
dd.innerHTML = def.definition;
defList.appendChild(dd);
});
● The new DOM content:
<dl id="definitions">
<dt>Ajax</dt> <dd>Asynchronous JavaScript and XML</dd>
<dt>JavaScript</dt><dd>The standard browser scripting language</dd>
<dt>Grails</dt> <dd>The hippest server-side scripting language</dd>
</dl>
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 71
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
DOM APIs
Odds & Ends
symbols
syntax
JSON
data types
Language
DOM
window
document
query
traversal
manipulation
DOM APIs
DOM events
Deferred operations
old models
Event queue
Event
Model
collection
functions
closures
1st
class
Ajax event
handlers
Functional
Programming
syntax
encapsulation
ctor prototype
core
JSON
revisited
hybrid OO
no-class
OO
Programming
Event Model
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 72
© Copyright 2012, Software Alchemy
The Event Models(s)
● Traditional (AKA Level 0)
– Event handlers as tag attributes (eg, onclick)
– Event handlers set as Element properties
● Standard event model in DOM Level 2
– Event listeners are registered with the element
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 73
© Copyright 2012, Software Alchemy
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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 74
© Copyright 2012, Software Alchemy
Event Propagation
Netscape Model Microsoft Model
Element1
Element2
Event Capturing
Element1
Element2
Event Bubbling
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 75
© Copyright 2012, Software Alchemy
Traditional Event Handlers
● Assign handler on tag attribute
<a href="#" onclick="return LoginScreen.validateForm();">go</a>
● Assign handler with Element property
var goButton = document.getElementById("goButton");
goButton.onclick = function(event) { return Screen.validateForm(); };
● CONS:
– Limited to only one handler per element and
event type
– Poor separation of concerns: behavior mixed in
with structure
– Inconsistent event propagation
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 76
© Copyright 2012, Software Alchemy
DOM Level 2 Event Handlers
● 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 : EventTarget
eventPhase : EventPhaseEnum
timeStamp : DOMTimeStamp
stopPropagation() : void
preventDefault() : void
EventPhaseEnum
CAPTURING_PHASE = 1
AT_TARGET = 2
BUBBLING_PHASE = 3
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 77
© Copyright 2012, Software Alchemy
Standard Event Propagation
● The standard propagation model is a
combination of the proprietary models:
Element1
Element2
CAPTURE_PHASE
BUBBLING_PHASEAT_TARGET
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 78
© Copyright 2012, Software Alchemy
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>
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 79
© Copyright 2012, Software Alchemy
Event Registration (JS)
// Create the EventsLevel2 namespace
var EventsLevel2 = {
registerHandlers: function(capture) {
var outerBox = document.getElementById('outerBox');
var innerBox = document.getElementById('innerBox');
outerBox.addEventListener("click", EventsLevel2, capture);
innerBox.addEventListener("click", EventsLevel2, capture);
},
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();
}
} // END of EventsLevel2 namespace definition
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 80
© Copyright 2012, Software Alchemy
Types of Events
● User events are the majority
– Clicking on buttons and links
– Entering text
– Submitting forms
● Ajax callbacks are handled as events
– Four states: OPEN, HEADERS_RECEIVED,
LOADING, DONE
● Timed events
– Periodic events (do over and over)
– Deferred events (do once after a delay)
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 81
© Copyright 2012, Software Alchemy
Event Queue
● All events that have an handler get added to a
queue that is sorted by the time of the event.
● Each script is executed sequentially in the
order the events happened.
● If any given script takes a long time then it can
delay the execution of other event handlers.
● SO... make your event handler scripts as
efficient as possible.
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 82
© Copyright 2012, Software Alchemy
Example Event Queue
● From our updated Ajax example:
Screen.buttonMouseOver
Screen.buttonClick
Screen.populateDefinitions
1331413671600
button/MouseOver
1331413671604
1331413671995
button/Click
1331413672005
1331413672025
Ajaxrequest/state=COMPLETE
1331413672032
4ms 30ms 7ms20ms391ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 83
© Copyright 2012, Software Alchemy
Events can be Delayed
● MouseOut event handler is delayed:
Screen.populateDefinitions
1331418196686
Ajaxrequest/state=COMPLETE
1331418198930
7ms 2244ms
Screen.buttonMouseOut
1331418198851
button/MouseOut
1331418198935
3ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 84
© Copyright 2012, Software Alchemy
Periodic Events
● The window object includes functions to setup
periodic activities:
● For example, a clock:
displayTime() {
var now = new Date();
var h = now.getHours();
var m = now.getMinutes();
var s = now.getSeconds();
var time = h + ":" + m + ":" + s;
var clockBox = document.getElementById('clockBox');
clockBox.innerHTML = time;
}
setInterval(displayTime, 1000);
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 85
© Copyright 2012, Software Alchemy
Periodic Clock Implementation
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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 86
© Copyright 2012, Software Alchemy
Periodic Events on the Queue
● Periodic Events are placed as evenly as
possible on the queue:
Clock.displayTime
1331596413012
periodicevent
1331596413017
5ms 1000ms
Clock.displayTime
1331596414012
periodicevent
1331596414016
4ms 1000ms
Clock.displayTime
1331596415022
periodicevent
1331596415026
4ms 1000ms
Clock.displayTime
1331596416019
periodicevent
1331596416023
4ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 87
© Copyright 2012, Software Alchemy
Periodic Events on the Queue
● Even with an expensive operation periodic
events are scheduled regularly:
Clock.displayTime
1331599720455
periodicevent
1331599721226
771ms 217ms
Clock.displayTime
1331599721443
periodicevent
1331599722217
774ms 219ms
Clock.displayTime
1331599722436
periodicevent
1331599723204
768ms
988ms 993ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 88
© Copyright 2012, Software Alchemy
Deferred Events
● A deferred event is a function that is placed on
to the event queue after a specific delay.
● You can mimic a periodic function by putting
the same operation back on the queue:
displayTime() {
var now = new Date();
var h = now.getHours();
var m = now.getMinutes();
var s = now.getSeconds();
var time = h + ":" + m + ":" + s;
var clockBox = document.getElementById('clockBox');
clockBox.innerHTML = time;
// Do it again every second
setTimeout("displayTime()", 1000);
}
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 89
© Copyright 2012, Software Alchemy
Deferred Events on the Queue
● When the operation is inexpensive this
mechanism works fairly well:
Clock.displayTime
1331597131485
deferredevent
1331597131490
5ms 995ms
Clock.displayTime
1331597132485
deferredevent
1331597132489
4ms 994ms
Clock.displayTime
1331597133492
deferredevent
1331597133496
4ms 1002ms
Clock.displayTime
1331597134498
deferredevent
1331597134502
4ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 90
© Copyright 2012, Software Alchemy
Deferred Events on the Queue
● But when the operation is expensive this
mechanism begins to drift:
993ms 991ms 995ms
Clock.displayTime
1331598308000
deferredevent
1331598308760
760ms
Clock.displayTime
1331598306248
deferredevent
1331598307009
761ms
Clock.displayTime
1331598304489
deferredevent
1331598305255
766ms
Clock.displayTime
1331598309755
deferredevent
1331598310517
762ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 91
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
DOM APIs
symbols
syntax
JSON
data types
Language
DOM
window
document
query
traversal
manipulation
DOM APIs
DOM events
Deferred operations
old models
Event queue
Event
Model
Firebug
Q&A
frameworks
IE debugging
Odds & Ends
collection
functions
closures
1st
class
Ajax event
handlers
Functional
Programming
syntax
encapsulation
ctor prototype
core
JSON
revisited
hybrid OO
no-class
OO
Programming
Odds & Ends
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 92
© Copyright 2012, Software Alchemy
Frameworks
● Low-level frameworks
– Makes DOM scripting easier
– Examples: jQuery, Prototype and Script-aculo-us
● High-level frameworks
– Provides GUI widgets
– Examples: Dojo, YUI and ExtJS
● Plugins for low-level frameworks
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 93
© Copyright 2012, Software Alchemy
Firebug
● The FireFox debugger
– Console and logging
– Command-line with access to code of the page
– Set breakpoints and walk-through execution
● Analyze:
– View script files
– View dynamic DOM structure
– View CSS rules and box structure
– View all downloaded files
– View Ajax HTTP requests and response
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 94
© Copyright 2012, Software Alchemy
Internet Explorer
● IE has been the bane of web developers for
years, but getting better
● Use IETester to test how your app works in a
variety of versions of IE
● Recent versions of IE have a decent debugger
and DOM inspector
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 95
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introduction
to JavaScript
DOM APIs
symbols
syntax
JSON
data types
Language
DOM
window
document
query
traversal
manipulation
DOM APIs
DOM events
Deferred operations
old models
Event queue
Event
Model
Firebug
Q&A
frameworks
IE debugging
Odds & Ends
collection
functions
closures
1st
class
Ajax event
handlers
Functional
Programming
syntax
encapsulation
ctor prototype
core
JSON
revisited
hybrid OO
no-class
OO
Programming
Q & A
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 96
© Copyright 2012, Software Alchemy
Resources
● Head First JavaScript (O'Reilly)
● JavaScript – The Definitive Edition (O'Reilly)
● DOM Scripting (friends of ed)
● jQuery Reference Guide (PACKT)
● designing with web standards, 2nd
ed. (New Riders)
● Mozilla: site
● ECMAScript standard: site and PDF
● Douglas Crawford's site and lectures
● JSON
● jQuery
● Others: Prototype, script.aculo.us, ExtJS, YUI, GWT, Dojo, and
so many more

Intro to-javascript

  • 1.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 1 © Copyright 2012, Software Alchemy Introduction to JavaScript Bryan Basham Software Alchemy basham47@gmail.com http://www.linkedin.com/in/SoftwareAlchemist Intro Introduction to JavaScript Functional Programming Language OO Programming DOM APIs Event Model Odds & Ends
  • 2.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 2 © Copyright 2012, Software Alchemy Introduction Web standards Separate of Concerns Intro Introduction to JavaScript Functional Programming Language OO Programming DOM APIs Event Model Odds & Ends
  • 3.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 3 © Copyright 2012, Software Alchemy Web Standards ● Supported by most browsers and mobile devices ● So what? – Abundant skilled developers ● Who cares? – Better accessibility and usability – Good tools – “Write once, publish everywhere” ● :-) well almost, of course there is always IE
  • 4.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 4 © Copyright 2012, Software Alchemy Example Page
  • 5.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 5 © Copyright 2012, Software Alchemy Separation of Concerns ● What to separate? – Structure – Presentation (aka style) – Behavior ● Unobtrusive JavaScript ● So what? – Clarity of code – Easy to modify and replace look and feel (LnF)
  • 6.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 6 © Copyright 2012, Software Alchemy Structure ● XHTML (or HTML v5) ● 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>
  • 7.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 7 © Copyright 2012, Software Alchemy Presentation ● Cascading Style Sheets (CSS) ● 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; }
  • 8.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 8 © Copyright 2012, Software Alchemy Behavior ● JavaScript (aka ECMAScript 262) ● Rich object-based and functional language ● Web behavior: – manipulate the page structure (DOM scripting) – handle user-generated events on elements – handle sync & async communication with server ● CONS: – some inconsistencies between browsers ● did I mention IE?
  • 9.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 9 © Copyright 2012, Software Alchemy Why is this important? . . . . . . . . . . . . . . . . . . . . . . . . . . . Client Server UI Code Data Behavior StructureStructure Presentation Behavior Data conversion invoke select next view generate enhance style / layout
  • 10.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 10 © Copyright 2012, Software Alchemy Language Fundamentals Web standards Separate of Concerns Intro Introduction to JavaScript Functional Programming OO Programming DOM APIs Event Model Odds & Ends symbols syntax JSON data types Language
  • 11.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 11 © Copyright 2012, Software Alchemy Symbols ● Symbols are similar to identifiers in Java ● Symbols can hold: – Data var name = “Bryan”; var age = 47; – Objects var obj = {}; – Functions function add(a, b) { return a + b; } ● Symbols are also used as keys in object hashes: { name: “Bryan”, age: 47 }
  • 12.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 12 © Copyright 2012, Software Alchemy Scope Rules ● Global scope <script> var G1 = 42; </script> ● Local scope function f() { var L1 = 47; return L1 + G1; } f() ==> 89 function g() { var L2 = 420; // this has local scope function h() { // local function var L2 = 42; // nested scoping return L2; } return L2 + h(); } g() ==> 462
  • 13.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 13 © Copyright 2012, Software Alchemy Namespaces ● Globals (vars and functions) create clutter ● Namespace is a 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
  • 14.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 14 © Copyright 2012, Software Alchemy Mimicking Java Packages ● You can nest namespaces to mimic packages: var INow = { utils : {}, domain : {}, screens : {} }; ● Then put functions, classes, etc in packages: INow.utils.map = function(array, funct) { ... }; INow.domain.Person = function() { /* class constructor */ };
  • 15.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 15 © Copyright 2012, Software Alchemy Data Types ● Numbers (64-bit floating point) 42 * 10.0 ==> 420 typeof 42 ==> “number” typeof 4.2 ==> “number” 42 / “10” ==> 4.2 ● Strings (Unicode, ' and “ delimited) “foo” 'she said “he said”' 'isn''t great!' typeof “foo” ==> “string” 42 + “10” ==> “4210” ● Booleans (true and false) typeof true ==> “boolean”
  • 16.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 16 © Copyright 2012, Software Alchemy More Data Types ● Dates var now = new Date(); var DoB = new Date(1964, 6, 22); // new Date(YYYY, MM, DD, h, m, s, ms) var ts = Date.parse(timestampString); now.getTime() // milliseconds since epoch // and so on (lots of methods) ● Regular expressions var re = new RegExp(“(d{2})W(d{2})W(d{4})”, “g”); // 07-22-1964 var re = /(d{2})W(d{2})W(d{4})/g; var re = new RegExp(); re.compile(“(d{2})W(d{2})W(d{4})”, “g”); – Modeled after Perl 5 syntax – Supports capture groups – Supports multi-line
  • 17.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 17 © Copyright 2012, Software Alchemy Even More Data Types ● Arrays ● Objects ● Functions ● Error (and subclasses) ● Special objects: Math and JSON ● null typeof null ==> “object” ● undefined typeof undefined ==> “undefined”
  • 18.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 18 © Copyright 2012, Software Alchemy Arrays ● Syntax var myArray = [13, 42, 47, 420]; ● Access myArray.length ==> 4 myArray[1] ==> 42 myArray[3] ==> 420 myArray[3] = 120; myArray[3] ==> 120 ● Iteration for ( var i=0; i<myArray.length; i++ ) { console.info(“myArray[“ + i + “] is “ + myArray[i]); }
  • 19.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 19 © Copyright 2012, Software Alchemy Syntax Overview ● Based upon Java syntax for: – Literals, expressions and operators – Declarations: ● Loosely-typed variables ● Functions – Statements ● But not: – Type structures: classes nor interfaces – Concurrency constructs: JS is single-threaded
  • 20.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 20 © Copyright 2012, Software Alchemy Special Operators ● Equality operator (==) vs Identify op (===) 42 == new Number(42) ==> true 42 == “42” ==> true 42 === new Number(42) ==> false 42 === “42” ==> false ● The typeof operator returns a type name typeof (42) ==> “number” typeof [42, 47] ==> “object” // WTF? typeof { foo:42 } ==> “object” – Complete list: boolean, number, string, function, undefined, and object ● The void operator always returns undefined void( /* some calculation */ ) ==> undefined
  • 21.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 21 © Copyright 2012, Software Alchemy Special Operators ● The delete operator removes an object entry var obj = { foo: 47, bar: 42 }; obj.foo ==> 47 delete obj.foo ==> true obj.foo ==> undefined ● The in operator 'foo' in obj ==> true ● The get and set operators (but... not in IE) var obj = { get foo() { return 47; }, set bar(v) { this._bar = v; }, get bar() { return “Hello ” + this._bar; } }; obj.foo ==> 47 obj.foo = 42; // but no change to obj obj.bar = “Bryan”; obj.bar ==> “Hello Bryan” obj._bar ==> “Bryan”
  • 22.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 22 © Copyright 2012, Software Alchemy Special Statements ● The for-in statement for ( var prop in obj ) { console.info(“prop '%s' is %o”, prop, obj[prop]); } ==> prop 'foo' is 47 prop 'bar' is “Hello Bryan” prop '_bar' is “Bryan” – Warning: more in an object than meets the eye ● The with statement with (obj) { console.info(“obj.foo is %d”, foo); bar = “Fred”; } obj.bar ==> “Hello Fred” – Warning: this statement is tricky to use properly
  • 23.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 23 © Copyright 2012, Software Alchemy Special functions ● The eval function eval(“2 * 3”) ==> 6 – Warning: use with caution ● The call function function addUp() { var sum = 0; for ( var i=0; i < arguments.length; i++ ) sum += arguments[i]; return sum; } addUp.call(null, 1, 2, 3, 4, 5); ==> 15 ● The apply function addUp.apply(null, [1, 2, 3, 4, 5]); ==> 15
  • 24.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 24 © Copyright 2012, Software Alchemy JavaScript Object Notation ● JSON, created by Douglas Crawford, is a string notation for JS objects – Just a subset; doesn't include functions – Native support in ECMAScript v4+ – May require a library, json.js, for old browsers – Don't use built-in eval function ● Used mostly to pass data between browsers and servers ● Put also becoming popular in other contexts, such as NoSQL data stores
  • 25.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 25 © Copyright 2012, Software Alchemy Native Support ● ECMAScript v4 defines the JSON object ● Generate JSON strings this way: var obj = { name: "Bryan", age: 47 } var str = JSON.stringify(obj) ==> "{"name":"Bryan","age":47}" ● Parse JSON strings this way: var obj2 = JSON.parse(str) obj2.name ==> "Bryan" obj2.age ==> 47 obj == obj2 ==> false ● Works in: IE8+, FF3.1+, Safari 4+, Chrome 3+, and Opera 10.5
  • 26.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 26 © Copyright 2012, Software Alchemy Web standards Separate of Concerns Intro Introduction to JavaScript DOM APIs Event Model Odds & Ends symbols syntax JSON data types Language syntax encapsulation ctor prototype core JSON revisited hybrid OO no-class OO Programming Functional Programming Object-Oriented Programming
  • 27.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 27 © Copyright 2012, Software Alchemy Object Creation ● Creating an object var O1 = new Object(); O1.a = 47; O1.method = function() { console.info(this.a); }; typeof O1 ==> "object" ● OR as a literal var O1 = { A : 47, method : function() { console.info(this.a); } } ● Remember “namespaces”? Just objects
  • 28.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 28 © Copyright 2012, Software Alchemy Object Property Access ● Access object attributes O1.a ==> 47 O1.a = 42; O1.method() ==> displays '42' in the console ● Objects can also be treated as associative arrays (aka hash maps) O1["a"] ==> 42 O1["a"] = 420; O1["method"]() ==> displays '420' in the console var prop = “a”; O1[prop] ==> 42
  • 29.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 29 © Copyright 2012, Software Alchemy JavaScript Core Classes ● Built-in – Object – Date – RegExp – Error (and subclasses) ● Wrappers – String, Number and Boolean ● Odd balls – Function and Array
  • 30.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 30 © Copyright 2012, Software Alchemy But wait... no classes ● You can't create classes in JavaScript class Range { /* code here */ } // NO SUCH SYNTAX ● You can only create object constructors typeof Date ==> "function" var Range = function(start, end) { this.start = start; this.end = end; } var r1 = new Range(42, 47); r1.start ==> 42 r1.end ==> 47 var r2 = new Range(13, 420); r2.start ==> 13 r2.end ==> 420 r1 #111:Range start = 42 end = 47 r2 #222:Range start = 1 end = 10
  • 31.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 31 © Copyright 2012, Software Alchemy Encapsulation ● Ugh.. these attributes are public r2.start = 520; r2.start ==> 520 // Semantics broken: the “start” is after the “end” ● Closures allow us to hide private data var Range = function(start, end) { this.getStart = function() { return start; } this.getEnd = function() { return end; } } var r1 = new Range(42, 47); r1.start ==> undefined r1.getStart() ==> 42 r1.getEnd() ==> 47 var r2 = new Range(13, 420); r2.getStart() ==> 13 r2.getEnd() ==> 420
  • 32.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 32 © Copyright 2012, Software Alchemy Encapsulation Object Model r1 #111:Range getStart getEnd #987:CallObj start = 42 end = 47 #876:CallObj start = 13 end = 420 function() { return start; } function() { return end; } r2 #222:Range getStart getEnd function() { return start; } function() { return end; }
  • 33.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 33 © Copyright 2012, Software Alchemy Encapsulation (2) ● Creating setters var Range = function(start, end) { this.getStart = function() { return start; } this.setStart = function(x) { if ( x <= end ) { start = x; } else { throw new Error(“illegal value”); } } this.getEnd = function() { return end; } this.setEnd = function(x) { /* like above */ } } var r = new Range(42, 47); r.getStart() ==> 42 r.setStart(13) r.getStart() ==> 13 r.setStart(50) // throws an Error r.getStart() ==> 13
  • 34.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 34 © Copyright 2012, Software Alchemy But... this too has problems ● This pattern creates lots of object-specific functions r1 #111:Range getStart setStart getEnd setEnd #222:Range getStart setStart getEnd setEnd function() {...} function(x) {...} function() {...} function(x) {...} function() {...} function(x) {...} function() {...} function(x) {...} r2 #987:CallObj start = 42 end = 47 #876:CallObj start = 13 end = 420
  • 35.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 35 © Copyright 2012, Software Alchemy Another Class-like Idiom ● Constructors have prototypes var Range = function(st, en) { this.start = st; this.end = en; } // Setup shared Range object methods Range.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 objects var 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);
  • 36.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 36 © Copyright 2012, Software Alchemy Another Class-like Idiom ● Function are reused across all objects Range.prototype getStart setStart getEnd setEnd function() {...} function(x) {...} function() {...} function(x) {...} r1 #111:Range start = 42 end = 47 r2 #222:Range start = 13 end = 420 r3 #333:Range start = 1.2 end = 3.14 r4 #444:Range start = 1 end = 10
  • 37.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 37 © Copyright 2012, Software Alchemy Hybrid OO Idiom var Circle = function(radius) { // Create privileged methods this.getRadius = function () { return radius; } } // Create public, but non-privileged methods Circle.prototype.getDiameter = function() { return this.getRadius() * 2; } Circle.prototype.getArea = function() { return Circle.PI * this.getRadius() * this.getRadius(); } // Create class constants Circle.PI = 3.14159; var c1 = new Circle(4.2); c1.getRadius() ==> 4.2 c1.getDiameter() ==> 8.4 c1.getArea() ==> 55.4176476 var c2 = new Circle(10); c1.getRadius() ==> 10 c1.getDiameter() ==> 20 c1.getArea() ==> 314.159
  • 38.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 38 © Copyright 2012, Software Alchemy Object model of hybrid OO Circle.prototype getDiameter getArea 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; }
  • 39.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 39 © Copyright 2012, Software Alchemy Advanced Class Features ● Admittedly these “class-like” programming idioms are awkward ● Mimicking class inheritance is even more complex ● They have their place (simple domain model) ● There are other, more advanced, inheritance mechanisms – Such as “prototypal inheritance” – See Douglas Crawford on Resource slide at end
  • 40.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 40 © Copyright 2012, Software Alchemy JSON Revisited ● 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); ● But what about our objects? var c1 = new Circle(4.2); var c1Str = JSON.stringify(c1); // "{}" WTF?!?! Where's my object?
  • 41.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 41 © Copyright 2012, Software Alchemy Hybrid-Class JSON Methods // Create the Circle class constructor function Circle(radius) { ... }; // 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); c.getArea() ==> 5541.76476 var cStr = JSON.stringify(c); var newC = JSON.parse(cStr, MyJSON.classReviver); newC.getArea() ==> 5541.76476
  • 42.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 42 © Copyright 2012, Software Alchemy JSON for Circle ● The Circle instance method toJSON preforms conversion from object to string. var c1 = new Circle(42); c1.getArea(); // 5541.76476 var c1Str = JSON.stringify(obj); // '""Circle(42)""' ● The JSON.parse method uses my 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.
  • 43.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 43 © Copyright 2012, Software Alchemy Web standards Separate of Concerns Intro Introduction to JavaScript DOM APIs Event Model Odds & Ends symbols syntax JSON data types Language syntax encapsulation ctor prototype core JSON revisited hybrid OO no-class OO Programming collection functions closures 1st class Ajax event handlers Functional Programming Functional Programming
  • 44.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 44 © Copyright 2012, Software Alchemy Function Creation ● Definition syntax function square(x) { return x * x; } square(12) ==> 144 typeof square ==> “function” ● OR as a variable var square = function(x) { return x * x; }; // lambda function (Lisp) square(12) ==> 144 ● OR as an object var square = new Function(“x”, “return x * x;”); square(12) ==> 144 ● ...these are all the same
  • 45.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 45 © Copyright 2012, Software Alchemy Invoking Functions ● Imagine the function: function add(a, b, c, d) { c = (c != undefined) ? c : 0; d = (d != undefined) ? d : 0; return a + b + c + d; } ● Don't have to give all arguments: add(1, 2) ==> 3 add(1, 2, 3) ==> 6 add(1, 2, 3, 4) ==> 10 ● Too many arguments are ignored: add(1, 2, 3, 4, 5, 6, 7) ==> 10
  • 46.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 46 © Copyright 2012, Software Alchemy Accessing Function Arguments ● You can create a function that takes any number of arguments: function addAll() { var sum = 0; for ( var idx=0; idx<arguments.length; idx++ ) { sum += arguments[idx]; } return sum; } add(1, 2) ==> 3 add(1, 2, 3) ==> 6 add(1, 2, 3, 4) ==> 10 add(1, 2, 3, 4, 5) ==> 15
  • 47.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 47 © Copyright 2012, Software Alchemy 1st Class Citizens ● Can store functions in variables ● Can store functions in objects – Like we did with privileged methods in the hybrid class idiom defined in the constructor function ● Can return functions from other functions ● Can pass functions in as arguments function isOdd(n) { return (n % 2) == 1; } function not(predicate) { return function(x) { return ! predicate(x); }; } var isEven = not(isOdd); isEven(2) ==> true isEven(5) ==> false
  • 48.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 48 © Copyright 2012, Software Alchemy Collections ● Example 1: function map(array, funct) { var newArray = new Array(); for ( var i=0; i<array.length; i++ ) { newArray[i] = funct(array[i]); } return newArray; } // Run unit tests function square(x) { return x * x; } var myArray = [13, 42, 47]; map( myArray, square ); ==> [169, 1764, 2209]
  • 49.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 49 © Copyright 2012, Software Alchemy Collections ● Example 2: function find(array, pred) { for ( var i=0; i<array.length; i++ ) { var value = array[i]; if ( pred(value) ) return value; } } // Run unit tests function isOdd(n) { return (n % 2) == 1; } var myArray = [13, 42, 47]; function isShort(s) { return s.length <= 3; } var myStrings = [“the”, “quick”, “brown”, “fox”]; find( myArray, isOdd ); ==> 13 find( myStrings, not(isShort) ); ==> “quick”
  • 50.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 50 © Copyright 2012, Software Alchemy Collections ● Example 3: function gather(array, pred) { var newArray = []; for ( var i=0; i<array.length; i++ ) { var value = array[i]; if ( pred(value) ) newArray.push(value); } return newArray; } // Run unit tests function isOdd(n) { return (n % 2) == 1; } var myArray = [13, 42, 47]; function isShort(s) { return s.length <= 3; } var myStrings = [“the”, “quick”, “brown”, “fox”]; gather( myArray, isOdd ); ==> [13, 47] gather( myStrings, not(isShort) ); ==> [“quick”, “brown”]
  • 51.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 51 © Copyright 2012, Software Alchemy Closures ● Closures hold state within a function function makeCutoffFunction(nTimes, funct) { return function(x) { // creating a new function object nTimes--; // access to local state variable if ( nTimes >= 0 ) { return funct(x); // execute the function } }; } var squareOnce = makeCutoffFunction( 1, square ); squareOnce(12) ==> 144 squareOnce(13) ==> void var logThrice = makeCutoffFunction( 3, console.info ); logThrice("first log message"); // log once logThrice("second log message"); // log twice logThrice("third log message"); // log thrice logThrice("fourth log message"); // stops logging
  • 52.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 52 © Copyright 2012, Software Alchemy Event Handlers ● Example: <button onclick=”this.className = 'red'”> Click me </button> ● Script is treated as a function: var buttonClickFunction = function() { this.className = 'red'; } ● Applied to the element object when clicked: buttonClickFunction.apply(buttonElement)
  • 53.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 53 © Copyright 2012, Software Alchemy Ajax ● Asynchronous JavaScript and XML – Perform HTTP requests without a page refresh – Responses area 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 becoming a standard – See: http://www.w3.org/TR/XMLHttpRequest/
  • 54.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 54 © Copyright 2012, Software Alchemy Creating an Ajax Request var 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
  • 55.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 55 © Copyright 2012, Software Alchemy Sending an Ajax Request var MyAjax = { createRequest : function() {}, // from previous slide sendRequest : function(url, requestData, callbackFunction) { var request = MyAjax.createRequest(); request.open("POST", url, true); request.setRequestHeader("Content-Type", "application/json"); 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
  • 56.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 56 © Copyright 2012, Software Alchemy Ajax Example ● Click on the button and JS requests the list of definitions from the server: ● Here's what the HTTP request looks like in Firebug:
  • 57.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 57 © Copyright 2012, Software Alchemy Ajax Example ● Populate a definition list when clicking a button <button onclick="Screen.buttonHandler()">Click me</button> <dl id="definitions"></dl> var Screen = { buttonHandler : function() { MyAjax.sendRequest("/TestJS/lesson/ajaxDefinitions", null, Screen.populateDefinitions); }, populateDefinitions : function(responseText) { var definitions = JSON.parse(responseText); var defList = document.getElementById('definitions'); each(definitions, function (def) { var dt = document.createElement('dt'); dt.innerHTML = def.name; defList.appendChild(dt); var dd = document.createElement('dd'); dd.innerHTML = def.definition; defList.appendChild(dd); }); } }
  • 58.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 58 © Copyright 2012, Software Alchemy Web standards Separate of Concerns Intro Introduction to JavaScript DOM APIs Event Model Odds & Ends symbols syntax JSON data types Language DOM window document query traversal manipulation DOM APIs collection functions closures 1st class Ajax event handlers Functional Programming syntax encapsulation ctor prototype core JSON revisited hybrid OO no-class OO Programming DOM APIs
  • 59.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 59 © Copyright 2012, Software Alchemy Window ● The window object is the “global object” ● Control methods: close, focus, blur, move, open, print and resize window navigator frames[] location history document screen
  • 60.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 60 © Copyright 2012, Software Alchemy Document ● The document object represents the structure of the current web page ● Provides easy access to critical elements document anchors[] applets[] forms[] images[] links[] body
  • 61.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 61 © Copyright 2012, Software Alchemy 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>
  • 62.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 62 © Copyright 2012, Software Alchemy Document Example Model <HTML> <HEAD> <BODY> <DIV> <FORM> <OL> <LI> <FIELDSET> <LABEL> <LI> <INPUT “username”> <LABEL> <A><INPUT “userpass”>
  • 63.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 63 © Copyright 2012, Software Alchemy Node Document Element CharacterData Text Comment CDATASection 1 childNodes parentNode 1 0..* 0..* The relationship between the Element and the abstract CharacterData type is implied by the Node's ability to contain children of any Node subtype, such as Text or Comment. documentElement {AKA: the root node} DOM Type Hierarchy (partial)
  • 64.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 64 © Copyright 2012, Software Alchemy DOM Traversal API ● The Node provides the traversal access: Node parentNode : Node childNodes : NodeList firstChild : Node lastChild : Node previousSibling : Node nextSibling : Node hasChildNodes() : boolean 1 0..* childNodes parentNode
  • 65.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 65 © Copyright 2012, Software Alchemy Traversal Example LI:Element LABEL:Element INPUT:Element A:Element "password":Text "go":Text parentNode firstChild lastChild nextSibling previousSibling <li> <label for="password">Password</label> <input id="password" name="userpass" type="password" /> <a href="#">go</a> </li>
  • 66.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 66 © Copyright 2012, Software Alchemy Traversal 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
  • 67.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 67 © Copyright 2012, Software Alchemy DOM Query APIs Document getElementsByTagName(tagName) : NodeList getElementById(elementId) : Element Element tagName : DOMString getElementsByTagName(tagName) : NodeList getElementsByClassName(clsName) : NodeList Node 1 documentElement {AKA: the root node} NodeList length : long [idx] : Node item(idx) : Node
  • 68.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 68 © Copyright 2012, Software Alchemy Query the DOM ● Find an element by its id // retrieves all form input elements var myForm = document.getElementById('loginForm') ● Find a list of elements by tag type // retrieves all <input> elements in the whole document document.getElementsByTagName('input') // retrieves all <input> elements in the <form id='loginForm'>...</form> myForm.getElementsByTagName('input')
  • 69.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 69 © Copyright 2012, Software Alchemy DOM Manipulation Document createElement(tagName) : Element createTextNode(data) : Text createCDATASection(data) : CDATASection Element tagName : DOMString hasAttribute(attrName) : boolean getAttribute(attrName) : DOMString setAttribute(attrName, attrValue) removeAttribute(attrName) 1 documentElement {AKA: the root node} Node insertBefore replaceChild removeChild appendChild
  • 70.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 70 © Copyright 2012, Software Alchemy Manipulation Example ● From the Ajax example: start with empty <dl> <dl id="definitions"></dl> ● Ajax callback fills in the list var defList = document.getElementById('definitions'); each(definitions, function (def) { var dt = document.createElement('dt'); dt.innerHTML = def.name; defList.appendChild(dt); var dd = document.createElement('dd'); dd.innerHTML = def.definition; defList.appendChild(dd); }); ● The new DOM content: <dl id="definitions"> <dt>Ajax</dt> <dd>Asynchronous JavaScript and XML</dd> <dt>JavaScript</dt><dd>The standard browser scripting language</dd> <dt>Grails</dt> <dd>The hippest server-side scripting language</dd> </dl>
  • 71.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 71 © Copyright 2012, Software Alchemy Web standards Separate of Concerns Intro Introduction to JavaScript DOM APIs Odds & Ends symbols syntax JSON data types Language DOM window document query traversal manipulation DOM APIs DOM events Deferred operations old models Event queue Event Model collection functions closures 1st class Ajax event handlers Functional Programming syntax encapsulation ctor prototype core JSON revisited hybrid OO no-class OO Programming Event Model
  • 72.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 72 © Copyright 2012, Software Alchemy The Event Models(s) ● Traditional (AKA Level 0) – Event handlers as tag attributes (eg, onclick) – Event handlers set as Element properties ● Standard event model in DOM Level 2 – Event listeners are registered with the element
  • 73.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 73 © Copyright 2012, Software Alchemy 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
  • 74.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 74 © Copyright 2012, Software Alchemy Event Propagation Netscape Model Microsoft Model Element1 Element2 Event Capturing Element1 Element2 Event Bubbling
  • 75.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 75 © Copyright 2012, Software Alchemy Traditional Event Handlers ● Assign handler on tag attribute <a href="#" onclick="return LoginScreen.validateForm();">go</a> ● Assign handler with Element property var goButton = document.getElementById("goButton"); goButton.onclick = function(event) { return Screen.validateForm(); }; ● CONS: – Limited to only one handler per element and event type – Poor separation of concerns: behavior mixed in with structure – Inconsistent event propagation
  • 76.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 76 © Copyright 2012, Software Alchemy DOM Level 2 Event Handlers ● 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 : EventTarget eventPhase : EventPhaseEnum timeStamp : DOMTimeStamp stopPropagation() : void preventDefault() : void EventPhaseEnum CAPTURING_PHASE = 1 AT_TARGET = 2 BUBBLING_PHASE = 3
  • 77.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 77 © Copyright 2012, Software Alchemy Standard Event Propagation ● The standard propagation model is a combination of the proprietary models: Element1 Element2 CAPTURE_PHASE BUBBLING_PHASEAT_TARGET
  • 78.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 78 © Copyright 2012, Software Alchemy 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>
  • 79.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 79 © Copyright 2012, Software Alchemy Event Registration (JS) // Create the EventsLevel2 namespace var EventsLevel2 = { registerHandlers: function(capture) { var outerBox = document.getElementById('outerBox'); var innerBox = document.getElementById('innerBox'); outerBox.addEventListener("click", EventsLevel2, capture); innerBox.addEventListener("click", EventsLevel2, capture); }, 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(); } } // END of EventsLevel2 namespace definition
  • 80.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 80 © Copyright 2012, Software Alchemy Types of Events ● User events are the majority – Clicking on buttons and links – Entering text – Submitting forms ● Ajax callbacks are handled as events – Four states: OPEN, HEADERS_RECEIVED, LOADING, DONE ● Timed events – Periodic events (do over and over) – Deferred events (do once after a delay)
  • 81.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 81 © Copyright 2012, Software Alchemy Event Queue ● All events that have an handler get added to a queue that is sorted by the time of the event. ● Each script is executed sequentially in the order the events happened. ● If any given script takes a long time then it can delay the execution of other event handlers. ● SO... make your event handler scripts as efficient as possible.
  • 82.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 82 © Copyright 2012, Software Alchemy Example Event Queue ● From our updated Ajax example: Screen.buttonMouseOver Screen.buttonClick Screen.populateDefinitions 1331413671600 button/MouseOver 1331413671604 1331413671995 button/Click 1331413672005 1331413672025 Ajaxrequest/state=COMPLETE 1331413672032 4ms 30ms 7ms20ms391ms
  • 83.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 83 © Copyright 2012, Software Alchemy Events can be Delayed ● MouseOut event handler is delayed: Screen.populateDefinitions 1331418196686 Ajaxrequest/state=COMPLETE 1331418198930 7ms 2244ms Screen.buttonMouseOut 1331418198851 button/MouseOut 1331418198935 3ms
  • 84.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 84 © Copyright 2012, Software Alchemy Periodic Events ● The window object includes functions to setup periodic activities: ● For example, a clock: displayTime() { var now = new Date(); var h = now.getHours(); var m = now.getMinutes(); var s = now.getSeconds(); var time = h + ":" + m + ":" + s; var clockBox = document.getElementById('clockBox'); clockBox.innerHTML = time; } setInterval(displayTime, 1000);
  • 85.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 85 © Copyright 2012, Software Alchemy Periodic Clock Implementation 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
  • 86.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 86 © Copyright 2012, Software Alchemy Periodic Events on the Queue ● Periodic Events are placed as evenly as possible on the queue: Clock.displayTime 1331596413012 periodicevent 1331596413017 5ms 1000ms Clock.displayTime 1331596414012 periodicevent 1331596414016 4ms 1000ms Clock.displayTime 1331596415022 periodicevent 1331596415026 4ms 1000ms Clock.displayTime 1331596416019 periodicevent 1331596416023 4ms
  • 87.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 87 © Copyright 2012, Software Alchemy Periodic Events on the Queue ● Even with an expensive operation periodic events are scheduled regularly: Clock.displayTime 1331599720455 periodicevent 1331599721226 771ms 217ms Clock.displayTime 1331599721443 periodicevent 1331599722217 774ms 219ms Clock.displayTime 1331599722436 periodicevent 1331599723204 768ms 988ms 993ms
  • 88.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 88 © Copyright 2012, Software Alchemy Deferred Events ● A deferred event is a function that is placed on to the event queue after a specific delay. ● You can mimic a periodic function by putting the same operation back on the queue: displayTime() { var now = new Date(); var h = now.getHours(); var m = now.getMinutes(); var s = now.getSeconds(); var time = h + ":" + m + ":" + s; var clockBox = document.getElementById('clockBox'); clockBox.innerHTML = time; // Do it again every second setTimeout("displayTime()", 1000); }
  • 89.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 89 © Copyright 2012, Software Alchemy Deferred Events on the Queue ● When the operation is inexpensive this mechanism works fairly well: Clock.displayTime 1331597131485 deferredevent 1331597131490 5ms 995ms Clock.displayTime 1331597132485 deferredevent 1331597132489 4ms 994ms Clock.displayTime 1331597133492 deferredevent 1331597133496 4ms 1002ms Clock.displayTime 1331597134498 deferredevent 1331597134502 4ms
  • 90.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 90 © Copyright 2012, Software Alchemy Deferred Events on the Queue ● But when the operation is expensive this mechanism begins to drift: 993ms 991ms 995ms Clock.displayTime 1331598308000 deferredevent 1331598308760 760ms Clock.displayTime 1331598306248 deferredevent 1331598307009 761ms Clock.displayTime 1331598304489 deferredevent 1331598305255 766ms Clock.displayTime 1331598309755 deferredevent 1331598310517 762ms
  • 91.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 91 © Copyright 2012, Software Alchemy Web standards Separate of Concerns Intro Introduction to JavaScript DOM APIs symbols syntax JSON data types Language DOM window document query traversal manipulation DOM APIs DOM events Deferred operations old models Event queue Event Model Firebug Q&A frameworks IE debugging Odds & Ends collection functions closures 1st class Ajax event handlers Functional Programming syntax encapsulation ctor prototype core JSON revisited hybrid OO no-class OO Programming Odds & Ends
  • 92.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 92 © Copyright 2012, Software Alchemy Frameworks ● Low-level frameworks – Makes DOM scripting easier – Examples: jQuery, Prototype and Script-aculo-us ● High-level frameworks – Provides GUI widgets – Examples: Dojo, YUI and ExtJS ● Plugins for low-level frameworks
  • 93.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 93 © Copyright 2012, Software Alchemy Firebug ● The FireFox debugger – Console and logging – Command-line with access to code of the page – Set breakpoints and walk-through execution ● Analyze: – View script files – View dynamic DOM structure – View CSS rules and box structure – View all downloaded files – View Ajax HTTP requests and response
  • 94.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 94 © Copyright 2012, Software Alchemy Internet Explorer ● IE has been the bane of web developers for years, but getting better ● Use IETester to test how your app works in a variety of versions of IE ● Recent versions of IE have a decent debugger and DOM inspector
  • 95.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 95 © Copyright 2012, Software Alchemy Web standards Separate of Concerns Intro Introduction to JavaScript DOM APIs symbols syntax JSON data types Language DOM window document query traversal manipulation DOM APIs DOM events Deferred operations old models Event queue Event Model Firebug Q&A frameworks IE debugging Odds & Ends collection functions closures 1st class Ajax event handlers Functional Programming syntax encapsulation ctor prototype core JSON revisited hybrid OO no-class OO Programming Q & A
  • 96.
    RJUG: 13-March-2012 Bryan Basham– Introduction to JavaScript Slide 96 © Copyright 2012, Software Alchemy Resources ● Head First JavaScript (O'Reilly) ● JavaScript – The Definitive Edition (O'Reilly) ● DOM Scripting (friends of ed) ● jQuery Reference Guide (PACKT) ● designing with web standards, 2nd ed. (New Riders) ● Mozilla: site ● ECMAScript standard: site and PDF ● Douglas Crawford's site and lectures ● JSON ● jQuery ● Others: Prototype, script.aculo.us, ExtJS, YUI, GWT, Dojo, and so many more