Upload
bryan-basham
View
1.443
Download
7
Embed Size (px)
DESCRIPTION
JavaScript is lingua franca of the Web. It's pervasive and since 1999 a standard ( ECMAScript 262). Yes, there are other technologies you can use: Flash, Java Applets, Dart, but none of these have the overwhelming support and community that JavaScript does. Over the years it has been maligned as a poorly designed language but I will argue that it has just been misunderstood. This talk will focus on the fundamentals of the language and its integration with the browser, the DOM and server communication via JSON and Ajax. In the talk Bryan will present: * Language fundamentals * Object-Oriented programming * Functional programming * DOM APIs * Event model * Odds and ends
Citation preview
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 1
© Copyright 2012, Software Alchemy
Introduction to JavaScript
Bryan BashamSoftware Alchemy
http://www.linkedin.com/in/SoftwareAlchemist
Intro
Introductionto JavaScript
FunctionalProgramming
Language
OOProgrammingDOM APIs
EventModel
Odds & Ends
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 2
© Copyright 2012, Software Alchemy
IntroductionWeb standards Separate of Concerns
Intro
Introductionto JavaScript
FunctionalProgramming
Language
OOProgrammingDOM APIs
EventModel
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 stylingul#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?
. . . . . . . . .. . . . . . . . .. . . . . . . . .
ClientServer
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
Introductionto JavaScript
FunctionalProgramming
OOProgrammingDOM APIs
EventModel
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:
– Datavar name = “Bryan”;var age = 47;
– Objectsvar obj = {};
– Functionsfunction 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 scopefunction f() { var L1 = 47; return L1 + G1;}f() ==> 89function 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 ==> 420typeof 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
● Datesvar 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 expressionsvar re = new RegExp(“(\d{2})\W(\d{2})\W(\d{4})”, “g”); // 07-22-1964var 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
● Syntaxvar myArray = [13, 42, 47, 420];
● AccessmyArray.length ==> 4
myArray[1] ==> 42myArray[3] ==> 420
myArray[3] = 120;myArray[3] ==> 120
● Iterationfor ( 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) ==> true42 == “42” ==> true42 === new Number(42) ==> false42 === “42” ==> false
● The typeof operator returns a type nametypeof (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 entryvar obj = { foo: 47, bar: 42 };obj.foo ==> 47delete obj.foo ==> trueobj.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 ==> 47obj.foo = 42; // but no change to objobj.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 statementfor ( var prop in obj ) { console.info(“prop '%s' is %o”, prop, obj[prop]);} ==>prop 'foo' is 47prop 'bar' is “Hello Bryan”prop '_bar' is “Bryan”
– Warning: more in an object than meets the eye● The with statementwith (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 functioneval(“2 * 3”) ==> 6
– Warning: use with caution● The call functionfunction 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 functionaddUp.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 ==> 47obj == 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
Introductionto JavaScript
DOM APIs
EventModel
Odds & Ends
symbols
syntax
JSON
data types
Language
syntax
encapsulation
ctor prototype
core
JSONrevisited
hybrid OO
no-class
OOProgramming
FunctionalProgramming
Object-Oriented Programming
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 27
© Copyright 2012, Software Alchemy
Object Creation
● 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); }}
● Remember “namespaces”? Just objects
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 28
© Copyright 2012, Software Alchemy
Object Property Access
● Access object attributesO1.a ==> 47O1.a = 42;O1.method() ==> displays '42' in the console
● Objects can also be treated as associative arrays (aka hash maps)
O1["a"] ==> 42O1["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 JavaScriptclass Range { /* code here */ } // NO SUCH SYNTAX
● 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 = 1end = 10
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 31
© Copyright 2012, Software Alchemy
Encapsulation
● Ugh.. these attributes are publicr2.start = 520;r2.start ==> 520 // Semantics broken: the “start” is after the “end”
● Closures allow us to hide private datavar Range = function(start, end) { 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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 32
© Copyright 2012, Software Alchemy
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; }
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 33
© Copyright 2012, Software Alchemy
Encapsulation (2)
● Creating settersvar 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() ==> 42r.setStart(13)r.getStart() ==> 13r.setStart(50) // throws an Errorr.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
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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 35
© Copyright 2012, Software Alchemy
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);
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
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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 37
© Copyright 2012, Software Alchemy
Hybrid OO Idiomvar Circle = function(radius) { // 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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 38
© Copyright 2012, Software Alchemy
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; }
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.76476var 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
Introductionto JavaScript
DOM APIs
EventModel
Odds & Ends
symbols
syntax
JSON
data types
Language
syntax
encapsulation
ctor prototype
core
JSONrevisited
hybrid OO
no-class
OOProgramming
collectionfunctions
closures
1st class
Ajax eventhandlers
FunctionalProgramming
Functional Programming
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 44
© Copyright 2012, Software Alchemy
Function Creation
● 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
● ...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) ==> 3add(1, 2, 3) ==> 6add(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) ==> 3add(1, 2, 3) ==> 6add(1, 2, 3, 4) ==> 10add(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 argumentsfunction isOdd(n) { return (n % 2) == 1; }function not(predicate) { return function(x) { return ! predicate(x); };}
var isEven = not(isOdd);isEven(2) ==> trueisEven(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 testsfunction 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 testsfunction 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 ); ==> 13find( 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 testsfunction 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 functionfunction 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) ==> 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
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 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
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 55
© Copyright 2012, Software Alchemy
Sending an Ajax Requestvar 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
Introductionto JavaScript
DOM APIs
EventModel
Odds & Ends
symbols
syntax
JSON
data types
Language
DOM
window
documentquery
traversal
manipulation
DOM APIscollectionfunctions
closures
1st class
Ajax eventhandlers
FunctionalProgramming
syntax
encapsulation
ctor prototype
core
JSONrevisited
hybrid OO
no-class
OOProgramming
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 10..*
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.
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 : NodechildNodes : NodeListfirstChild : NodelastChild : NodepreviousSibling : NodenextSibling : 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
firstC
hild 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) : NodeListgetElementById(elementId) : Element
Element
tagName : DOMString
getElementsByTagName(tagName) : NodeListgetElementsByClassName(clsName) : NodeList
Node
1
documentElement{AKA: the root node}
NodeList
length : long
[idx] : Nodeitem(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 elementsvar myForm = document.getElementById('loginForm')
● Find a list of elements by tag type// retrieves all <input> elements in the whole documentdocument.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) : ElementcreateTextNode(data) : TextcreateCDATASection(data) : CDATASection
Element
tagName : DOMString
hasAttribute(attrName) : booleangetAttribute(attrName) : DOMStringsetAttribute(attrName, attrValue)removeAttribute(attrName)
1
documentElement{AKA: the root node}
Node
insertBeforereplaceChildremoveChildappendChild
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 listvar 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
Introductionto JavaScript
DOM APIs
Odds & Ends
symbols
syntax
JSON
data types
Language
DOM
window
documentquery
traversal
manipulation
DOM APIs
DOM events
Deferred operations
old models
Event queue
EventModel
collectionfunctions
closures
1st class
Ajax eventhandlers
FunctionalProgramming
syntax
encapsulation
ctor prototype
core
JSONrevisited
hybrid OO
no-class
OOProgramming
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 propertyvar 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 : DOMStringtarget : EventTarget {an element}currentTarget : EventTargeteventPhase : EventPhaseEnumtimeStamp : DOMTimeStamp
stopPropagation() : voidpreventDefault() : void
EventPhaseEnum
CAPTURING_PHASE = 1AT_TARGET = 2BUBBLING_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
CAP
TUR
E_P
HAS
E
BUBB
LIN
G_P
HAS
EAT_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
Ajax request / 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
Ajax request / 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
periodic event
1331596413017
5ms 1000ms
Clock.displayTime
1331596414012
periodic event
1331596414016
4ms 1000ms
Clock.displayTime
1331596415022
periodic event
1331596415026
4ms 1000ms
Clock.displayTime
1331596416019
periodic event
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
periodic event
1331599721226
771ms 217ms
Clock.displayTime
1331599721443
periodic event
1331599722217
774ms 219ms
Clock.displayTime
1331599722436
periodic event
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
deferred event
1331597131490
5ms 995ms
Clock.displayTime
1331597132485
deferred event
1331597132489
4ms 994ms
Clock.displayTime
1331597133492
deferred event
1331597133496
4ms 1002ms
Clock.displayTime
1331597134498
deferred event
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
deferred event
1331598308760
760ms
Clock.displayTime
1331598306248
deferred event
1331598307009
761ms
Clock.displayTime
1331598304489
deferred event
1331598305255
766ms
Clock.displayTime
1331598309755
deferred event
1331598310517
762ms
RJUG: 13-March-2012
Bryan Basham – Introduction to JavaScript Slide 91
© Copyright 2012, Software Alchemy
Web standards Separate of Concerns
Intro
Introductionto JavaScript
DOM APIs
symbols
syntax
JSON
data types
Language
DOM
window
documentquery
traversal
manipulation
DOM APIs
DOM events
Deferred operations
old models
Event queue
EventModel
Firebug
Q&A
frameworks
IE debugging
Odds & Ends
collectionfunctions
closures
1st class
Ajax eventhandlers
FunctionalProgramming
syntax
encapsulation
ctor prototype
core
JSONrevisited
hybrid OO
no-class
OOProgramming
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
Introductionto JavaScript
DOM APIs
symbols
syntax
JSON
data types
Language
DOM
window
documentquery
traversal
manipulation
DOM APIs
DOM events
Deferred operations
old models
Event queue
EventModel
Firebug
Q&A
frameworks
IE debugging
Odds & Ends
collectionfunctions
closures
1st class
Ajax eventhandlers
FunctionalProgramming
syntax
encapsulation
ctor prototype
core
JSONrevisited
hybrid OO
no-class
OOProgramming
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