Upload
daniel-cousineau
View
947
Download
3
Embed Size (px)
DESCRIPTION
The second-half of the php|tek 2012 tutorial session "HTML5 and JavaScript"
Citation preview
HTML5 and JavaScriptPart Deux
Thursday, July 5, 12
Daniel Cousineau@dcousineau
Thursday, July 5, 12
History
Thursday, July 5, 12
MochaLiveScript
JavaScript
Brendan EichCTO, Mozilla Corp.
April 1995
Thursday, July 5, 12
JavaScriptECMAScript
ActionScript
JScript
Thursday, July 5, 12
Basics
Thursday, July 5, 12
Data Types•number
• string
•boolean
•object
•null
•NaN
•undefined
Thursday, July 5, 12
Strings
•Are Objects, have methods
Thursday, July 5, 12
"Foo" + "Bar"; //"FooBar"
var str = "Lorem Ipsum Dolor Sit Amet";
str.toLowerCase(); //"lorem ipsum dolor sit amet"str.toUpperCase(); //"LOREM IPSUM DOLOR SIT AMET"str.split(" "); //["Lorem", "Ispum", "Dolor", "Sit", "Amet"]str.substring(6,9); //"Ips"
new String("Lorem Ipsum Dolor Sit Amet") == str; //true
Strings
Thursday, July 5, 12
parseInt("56"); //56parseInt("42.567"); //42parseInt("asdf"); //NaNparseInt("5a6"); //5parseFloat("24.68"); //24.68parseFloat("asdf"); //NaNparseFloat("24a"); //24
String to Number
Thursday, July 5, 12
Objects
• “Dictionary” / “Associative Array”
•Key: Value or 'Key': Value
•Without ': A-Z0-9 only
•Does not keep intrinsic ordering
•Accessed keys using . (dot) or [] notation
Thursday, July 5, 12
var object = { foo: 'value', 'complex key': 0, bar: { nested: true }};
object.foo; //'value'object.['complex key']; //0object.bar.nested; //trueobject.bar['nested']; //trueobject['bar'].nested; //trueobject['bar']['nested']; //true
Objects
Thursday, July 5, 12
in or hasOwnProperty()
•Tough call:
•.hasOwnProperty() more consistent
•in checks inherited properties
•Used in for loop
Thursday, July 5, 12
var test = { foo: 'value', bar: 'value', baz: 'value'}
for (var key in test) { console.log(key + ": " + test[key]);}
//PRINTS://foo: value//bar: value//baz: value
in
Thursday, July 5, 12
Arrays
•Special object
•Numerical keys only
•Keeps intrinsic ordering
•Short ([]) and Long (new Array()) syntax
Thursday, July 5, 12
var arrayShort = [ 'one', 'two'];arrayShort[2] = 'three';
var arrayLong = new Array();arrayLong[0] = 'one';arrayLong[1] = 'two';arrayLong[2] = 'three';
//arrayShort: ["one", "two", "three"]//arrayLong: ["one", "two", "three"]
Arrays
Thursday, July 5, 12
var arr = [1,2,3,4,6];
arr.indexOf(2); //1arr.join(':'); //"1:2:3:4:6"arr.pop(); //6 //[1,2,3,4]arr.push(7); //5 //[1,2,3,4,7]arr.reverse(); //[7,4,3,2,1]arr.shift(); //1//[2,3,4,7]arr.unshift(8); //5//[8,2,3,4,7]arr.slice(1); //[2,3,4,7]arr.slice(1,3); //[2,3]arr.slice(-3); //[3,4,7]arr.slice(-3,-1); //[3,4]
Arrays
Thursday, July 5, 12
var arr1 = [1,2,3];var arr2 = [3,4,5];
arr1.concat(arr2); //[1,2,3,3,4,5]
Arrays
Thursday, July 5, 12
delete
•Removes element from an object
• “Removes element from an array”
•Not really, just sets it to undefined
Thursday, July 5, 12
Functions
•Are Objects as well
• “Elevated”
•You can use a named function before it is defined in code
•Function definitions are elevated to the top
Thursday, July 5, 12
function Foo() { //...}
Foo(); //validBar(); //valid
function Bar() { //...}
Functions
Thursday, July 5, 12
function Foo() { }
Foo.bar = "value";
'bar' in Foo; //trueFoo.bar == "value"; //true
Functions
Thursday, July 5, 12
Function Arguments
•No way to assign default arguments
•But arguments are not required
• If an argument is not specified, it is set to undefined
Thursday, July 5, 12
arguments
•A special variable found inside a function
•A not-quite array object containing all the function arguments
Thursday, July 5, 12
function sum() { var x = 0; for (var i = 0; i < arguments.length; ++i) { x += arguments[i]; } return x;}sum(1, 2, 3); //6
arguments
Thursday, July 5, 12
typeof
•Determines a variables type
•Returns a string
Thursday, July 5, 12
typeof true; //"boolean"typeof 12; //"number"typeof "string"; //"string"typeof []; //"object"typeof {}; //"object"typeof NaN; //"number"typeof null; //"object"typeof undefined; //"undefined"
function Foo() {}typeof Foo; //"function"
typeof
Thursday, July 5, 12
Comparison
•a == b / a != b
•A and B compared by value alone
•1 == “1” evaluates to true
•a === b / a !== b
•A and B compared by value and by type
•1 === “1” evaluates to false
Thursday, July 5, 12
window, document•Built in, global, Objects
•window
•Provides access to the browser window
•The “global” object: foo === window.foo
•Things like window.location.href, etc
•document
•Provides access to the current DOMThursday, July 5, 12
Closures
Thursday, July 5, 12
Closures
•First-Class
•Can assign functions to variables, pass as arguments and return as values
•Anonymous
•Not required to have a name
•A function that “closes over” variables defined outside itself
Thursday, July 5, 12
function Foo() { var count = 0; return function() { count = count + 1; return count; };}
var bar = Foo();
bar(); //1bar(); //2bar(); //3
Closures
Thursday, July 5, 12
function createAdder(amount) { return function(input) { return input + amount; };}
var add2 = createAdder(2);
add2(2); //4add2(8); //10
var add3 = createAdder(3);
add3(3); //6add3(7); //10
Closures
Thursday, July 5, 12
(function(exports, undefined){ //ALL your code here var localVar = "bar" globalVar = "baz"; exports.foo = "bat";})(window);
alert(localVar); //erroralert(globalVar); //"baz"alert(window.globalVar); //"baz"alert(foo); //"bat"alert(window.foo); //"bat"
Module Pattern
BEWARE: export (singular) is a reserved word in SafariThursday, July 5, 12
Scoping
Thursday, July 5, 12
Global & Local
•Functions are the only way to create new scopes
•Variables defined with var are local
•Variables defined without var are global
•Global variables are members of window
Thursday, July 5, 12
var outerScope = 10;var outerScope2 = 10;
function Foo() { var outerScope = 20; var innerScope = 20; globalVariable = 30; outerScope2 = 40;}
Foo();
alert(outerScope); //10alert(outerScope2); //40alert(innerScope); //erroralert(globalVariable); //30
Global & Local
Thursday, July 5, 12
function Foo() { var baz = 1; function Bar() { return baz; } return Bar();}
Foo(); //1
Lexical Scopingfunction Foo() { var baz = 1; return Bar();}
function Bar() { return baz;}
Foo(); //baz is not defined
Thursday, July 5, 12
Named functions are parsed and made available before general evaluation (thus “hoisted” to the top of the file).
Anonymous functions, or functions assigned to variables, require evaluation before they become available
foo(); //called foo!
function foo() { console.log('called foo!');}
foo(); //called foo!
bar(); //undefined is not a function
var bar = function() { console.log('called bar!');}
bar(); //called bar!
Hoisting
Thursday, July 5, 12
function makeAdder(a) { return function(b) { return a+b; }}
var two = makeAdder(2);two(1); //3two(2); //4two(3); //5
Practical: Currying
Thursday, July 5, 12
this
Thursday, July 5, 12
this
•Trips everyone up
•Special variable used within a function
•Refers to the “contextual object”
•Changes based on where a function executes
Thursday, July 5, 12
var Foo = { bar: "bar", baz: function() { return this.bar; }};
Foo.baz(); //"bar"
Foo.bar = "bat";Foo.baz(); //"bat"
var baz = Foo.baz;baz(); //undefined
this
Thursday, July 5, 12
var Foo = { bar: "bar", baz: function() { return this.bar; }};
Foo.bat = function() { return this.bar + "bat";};
Foo.bat(); //"barbat"
this
Thursday, July 5, 12
call & apply
•Methods in the function prototype
•Change the context in which a function executes!
Thursday, July 5, 12
var Foo = { bar: "bar", baz = function(param1, param2) { return this.bar + param1 + param2; }};
var Foo2 = { bar: "123"};
Foo.baz("baz", "bat"); //"barbazbat"
Foo.baz.apply(Foo2, "baz", "bat"); //"123bazbat"Foo.baz.call(Foo2, ["baz", "bat"]); //"123bazbat"
call & apply
Thursday, July 5, 12
function bind(func, context) { return function() { return func.call(context, arguments); }}
Practical: Binding
Thursday, July 5, 12
Exceptions
Thursday, July 5, 12
Exceptions
•All errors are thrown
•Classic try...catch...finally blocks
Thursday, July 5, 12
try { funcDoesNotExist();} catch (e) { alert(e); //ReferenceError: funcDoesNotExist is not defined} finally { //Always Executes}
Exceptions
Thursday, July 5, 12
function Foo() { throw new Error("Message");}
function Bar() { throw "Message";}
try { Foo();} catch (e) { e.message == "Message"; //true}
try { Bar();} catch (e) { e == "Message"; //true}
Exceptions
Thursday, July 5, 12
Prototype
Thursday, July 5, 12
OOP... Kinda...
•Almost no real difference between a dictionary and an object
•Named Functions double as object constructors
•Function objects contain a prototype dictionary that is copied to instance when using new
Thursday, July 5, 12
Foo‣ bar‣ prototype‣ baz‣ constructor‣ __proto__
function Foo() { //The "Constructor"}
Foo.bar = function() { //A "Static" Function}
Foo.prototype.baz = function() { //A "Method"};
OOP... Kinda...
Thursday, July 5, 12
instance‣ __proto__‣ baz‣ constructor‣ __proto__‣ ...
var instance = new Foo();
instance.baz(); //worksinstance.bar(); //error
Foo.bar(); //worksFoo.baz(); //errorFoo.prototype.baz(); //works
new
Thursday, July 5, 12
instance‣ bat‣ __proto__‣ baz‣ constructor‣ __proto__‣ ...
instance.bat = function() { /* ... */ }
instance.bat(); //works
Foo.bat(); //errorFoo.prototype.bat(); //error
new
Thursday, July 5, 12
function Foo(baz) { this.baz = baz;}
Foo.prototype.bar = function() { return this.baz;};
var foo1 = new Foo(1);var foo2 = new Foo(2);
foo1.bar(); //1foo2.bar(); //2
Foo.prototype.bar = function() { return this.baz * 2;};
foo1.bar(); //2foo2.bar(); //4
Overriding Prototype
Thursday, July 5, 12
Asynchronous
Thursday, July 5, 12
Asynchronous
• setTimeout, setInterval allow you to have code executing asynchronously while other code executes
Thursday, July 5, 12
var id = setInterval(function() { //Code to execute every 1000 milliseconds}, 1000);
//clearInterval(id); to stop
setInterval
Thursday, July 5, 12
var id = setTimeout(function() { //Code to execute after 1000 milliseconds have passed}, 1000);
//clearTimeout(id); to cancel
setTimeout
Thursday, July 5, 12
setInterval()
setTimeout()
Thursday, July 5, 12
setTimeout(function() { //Code to run in parallel //while the code after is //executed.}, 1);
//Code here will execute immediately//without waiting on the above
Nifty Trick
Thursday, July 5, 12
DOM
Thursday, July 5, 12
DOM
•Document Object Model
•API to interact with the HTML/XHTML document
Thursday, July 5, 12
Basic selection methods in native DOM
document .getElementById('foo');
document .getElementsByClassName('.bar');
document .getElementsByTagName('script');
DOM: Selection
Thursday, July 5, 12
Thursday, July 5, 12
var paragraph = document.createElement('p');var content = document.createTextNode("Lorem Ipsum");
paragraph.appendChild(content);paragraph.classList.add('my-class');
document.getElementsByTagName('body')[0].appendChild(paragraph);
DOM: Creation
Thursday, July 5, 12
Thursday, July 5, 12
Creates a script element, set its src and async properties
Insert the script before the first script tag in the body of the document
var script = document.createElement('script');script.src = "http://path.to/script.js";script.async = true;
var s = document .getElementsByTagName('script')[0];
s.parentNode .insertBefore(script, s);
Async Script Loading
Thursday, July 5, 12
DOM
https://developer.mozilla.org/en/Gecko_DOM_Reference
Thursday, July 5, 12
Debugging
Thursday, July 5, 12
Chrome/Safari Devel. Tools
Thursday, July 5, 12
Firefox FireBug
Thursday, July 5, 12
Console
•Provided by major browser vendors
•Useful for viewing logs, exceptions, real-time data dumping, and code execution within the current context
•Your best friend
•Though older IEs FREAK OUT when you leave it in, remove before deploy!
Thursday, July 5, 12
console
•Ditch alert(), this is your var_dump()
•console.log(arg1, arg2, ...)
•console.info Same as log
•console.warn Icon indicator
•console.error Stack trace
Thursday, July 5, 12
BEWARE
•console.log is not blocking
• In heavily asynchronous applications, sometimes value displayed is not value at the moment of the call
•Your if/else conditionals will work yet console.log will return something that should cause them to fail
Thursday, July 5, 12
Network
•Display all network requests via a gantt-like graph
•Shows browser-initiated (css, images, etc) and script initiated (ajax) alike
•Along with both request and response headers
Thursday, July 5, 12
Script
•Provides a familiar break-point debugging workflow
Thursday, July 5, 12
Coding Styles
Thursday, July 5, 12
Coding Styles
•Mostly your standard C based style techniques
•Special considerations
•Semi-colons? No semi-colons?
•Leading , ?
•Prototype Definition?
Thursday, July 5, 12
var dict = { foo: 'bar', baz: 'bat'};
var dict = { foo: 'bar' , baz: 'bat'};
Comma Style
Thursday, July 5, 12
var foo;var bar;var baz;
var foo , bar , baz;
var Declaration Style
Thursday, July 5, 12
function Foo() { }
Foo.prototype.bar = function(){ };
Prototype Stylefunction Foo() { }
Foo.prototype = { bar: function() { }}
Thursday, July 5, 12
Code Quality Tools
• JSLint http://www.jslint.com/
•By Crockford, extremely strict and inflexible. Code like Crockford!
• JSHint http://www.jshint.com/
•Fork, more flexible according to your own rules and preferences
Thursday, July 5, 12
Common Techniques
Thursday, July 5, 12
Grab global App dictionary, or create if not found
Add a function utility, is now globally accessible without fearing collision with other functioned similarly named
App = window.App || {};
App.utility = function() { //Globally available, no //conflicts};
Safe Extension
Thursday, July 5, 12
Immediately Invoked Function Expression
Function is defined then immediately invoked. Closest thing to a namespace/module system.
Prevents variable leakage into outer scopes
(function(exports){ exports.foo = function() { }; var bar = function() { };})(window);
foo(); //successbar(); //not found!
IIFE
Thursday, July 5, 12
Pro-Tip
•Create an application namespace as a dictionary in the global scope
•Add in any global level configuration values
Thursday, July 5, 12
JSON
Thursday, July 5, 12
JSON
Douglas CrockfordAwesome
2001
Thursday, July 5, 12
JSON• JavaScript Object Notation
•Serialization format that is basically JavaScript code minus comments
•Can be eval()’ed
•But don’t! Use JSON2.js or equivalent
•Minimal overhead compared to XML
•No parsers required, native mapping
Thursday, July 5, 12
{"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] }}}
JSON<menu id="file" value="File"> <popup> <menuitem value="New" onclick="CreateNewDoc()" /> <menuitem value="Open" onclick="OpenDoc()" /> <menuitem value="Close" onclick="CloseDoc()" /> </popup></menu>
Thursday, July 5, 12
BREAK HAMMER TIME
Thursday, July 5, 12
jQuery
Thursday, July 5, 12
jQuery
John ResigAuthor, jQuery
January 2006
Thursday, July 5, 12
jQuery
•Cross-browser JavaScript library
•Simplifies and normalizes DOM, AJAX, etc.
•Centers around using extended CSS selectors to grab an element(s)
Thursday, July 5, 12
Selectors
•Superset of CSS3 selectors
•Custom Pseudo-Classes
•Filters in jQuery parlance
Thursday, July 5, 12
Selectors
•$('selector') returns jQuery object for chaining purposes
•Chained methods will apply to all results if selector matches multiple elements
Thursday, July 5, 12
Finds all p tags that do not have the class special, and adds the class semi-special
$("p:not(.special)") .addClass("semi-special");
Selectors
Thursday, July 5, 12
Gets the value of the selected option in a select box
$('select option:selected').val();
Selectors
Thursday, July 5, 12
Tests matched element against selector, in this case the jQuery ‘visible’ selector
$('.foo').is(':visible');
Testing Elements
Thursday, July 5, 12
Custom Filters
• jQuery provides the ability to create custom filters
•:radio, :hidden, etc are custom filters provided by default
Thursday, July 5, 12
$("#foo") .html("<strong>bar</strong> baz");
jQuery<div id="foo"></div>
<div id="foo"> <strong>bar</strong> baz</div>
Thursday, July 5, 12
Chaining
•Most all jQuery methods are chain-able
• If $() returns > 1 element, methods invoked will apply to all matched
Thursday, July 5, 12
Find all ul with class first
Find elements of class foo that are children of the top level matched set
Apply the css style of color:red;
Pop the matching of .foo off the jQuery object
Find elements of class bar that are children of the top level matched set (ul.first)
Apply the css style of color:blue;
$('ul.first') .find('.foo') .css('color', 'red') .end().find('.bar') .css('color', 'blue') .end();
Chaining
Thursday, July 5, 12
Events
• jQuery wraps an event handling system
•Handles browser events, AJAX events, and custom events
Thursday, July 5, 12
$(document).ready(function() { //Only execute when the document fires //its onready event (page is done loading)});
$(document).bind('ready', function() { //Equivalent to the above});
$(function() { //Shortcut, equivalent to the above});
Events
Thursday, July 5, 12
$('img').hover(function(){ //Do something when user hovers over //any img tag});
Events
Thursday, July 5, 12
Events
•Event functions have the matched element from jQuery bound as this
Thursday, July 5, 12
Listen for click on a.foo
this will be the specific a.foo element that was clicked
$('a.foo').click(function(){ var $this = $(this) , href = $this.href(); //href will be the clicked //links href});
jQuery
Thursday, July 5, 12
Live Events
•Events using .bind are bound to the specific element at the specific point in time it was bound• New elements that match will not be included
•Using .on or .off produces a delegate listener that scans for bubbled events that match a selector• New elements that match said selector WILL be included
Thursday, July 5, 12
All a tags that exist at some point as a descendant of .grandparent will trigger this event on click
Any future a tags that are added as a descendant of .grandparent will trigger this event on click
$('.grandparent') .on('click', 'a', function(e){ var $target = $(e.target); //$target will *usually* //be the a tag, though //sometimes it will be a //nested tag });
Live Events
Thursday, July 5, 12
Create a Prototype object for example purposes, then create new instance.
The first click handler will fail. The keyword this will not be a reference to the instance of Foo as expected, but a reference to the matched DOM element that was clicked.
jQuery.proxy() will wrap your function such that further invocations will use the context you set for this
function Foo() {}
Foo.prototype.baz = function() {};Foo.prototype.bar = function() { this.baz();};
var instance = new Foo();
$('element').click(instance.bar);
$('element').click( jQuery.proxy( instance.bar, instance ););
Proxy
Thursday, July 5, 12
When .button is clicked, fade out img.preview over 600 milliseconds and then remove it from the DOM
$('.button').click(function(){ $('img.preview') .fadeOut(600, function() { $(this).remove(); });});
Animation
Thursday, July 5, 12
Animate the following attributes over the course of 5 seconds: opacity to 25% move to the right 50px toggle height
$('#book').animate({ opacity: 0.25, left: '+=50', height: 'toggle' }, 5000, function() { // Animation complete. });
animate
Thursday, July 5, 12
DOM Creation / Insertion
•Super easy! Provide html tag to $() and jQuery will create the element and return it wrapped in jQuery
•Second parameter is dictionary for properties
•Then use methods like .append() to insert
Thursday, July 5, 12
Creates a DIV tag
Creates an input (text) tag
Creates a span with the class of foo
$('<div>');
$('<input type="text" />');
$('<span>', { 'class': 'foo'});
DOM Creation
Thursday, July 5, 12
Replaces the content of #foo with:Testing
Replaces the content of #bar with:<strong>Testing</strong>
$('#foo') .html("<strong>Testing</strong>"); $('#bar') .text("<strong>Testing</strong>");
DOM Override
Thursday, July 5, 12
Insertion (inside):-append-appendTo-html-prepend-prependTo-textInsertion (outside):-after-before-insertAfter-insertBefore
$('<div>') .appendTo($('#foo'));
$('#foo') .append($('<span>'));
$('<div>') .prependTo($('#bar')); $('#baz') .after($('<span>'));
$('<div>') .insertBefore($('#baz'));
DOM Insertion
Thursday, July 5, 12
AJAX
•Asynchronous JavaScript And XML
•Though never use XML, use JSON
• jQuery has an AJAX library
•Wraps all the different browser quirks
• IE is weird
Thursday, July 5, 12
$.ajax({ url: "test.php", success: function(data){ $('div.status').addClass("done") .html(data); }});
AJAX
Thursday, July 5, 12
Cross-Domain
•Browser will not fire AJAX requests to a domain outside the one said JavaScript was loaded from
• If you include http://sub.domain.tld/file.js, it cannot make AJAX requests to http://another.tld/
• It can make requests to http://domain.tld/
Thursday, July 5, 12
JSONp
•Workaround to cross-domain
•Load like it is a javascript file (create an inject a script tag into the DOM)
•Response is a function (defined by a callback GET parameter) that executes and returns value
Thursday, July 5, 12
["api", "response"] callback(["api", "response"]);
JSONpdomain.tld/api.json domain.tld/api.jsonp?callback=callback
Thursday, July 5, 12
$.ajax({ dataType: 'jsonp' , url: 'http://search.twitter.com/search.json' , data: { q: "#tek12" } , success: function(resp) { jQuery.each(resp.results, function(id, tweet){ $('<div>', { 'class': 'tweet' }) .append($('<strong>', { 'class': 'user' , text: '@' + tweet.from_user })) .append($('<span>',{ 'class': 'text' , text: tweet.text })) .appendTo($('#tweets')); }); }});
JSONp
Thursday, July 5, 12
Create new :inline filter (checks if display is set to inline)
Works like any other native inline
$.expr[':'].inline = function(elem){ var $elem = $(elem) , disp = $elem.css('display'); return disp === 'inline';};
$('div a:inline') .css('color', 'red');
$('span:not(:inline)') .css('color', 'blue')
Extending: Custom Filters
Thursday, July 5, 12
(function($, global, undefined){
var defaults = { foo: "bar" };
var methods = { init: function(options) { // Merge user defined options options = $.extend(true, {}, defaults, options); return this; }, method: function() { }, }
$.fn.foo = function(method) { if( methods[method] ) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method == 'object' || !method) { return methods.init.apply(this, arguments); } else { $.error('Method ' + method + ' does not exist'); return undefined; } }
})(jQuery, window);
Thursday, July 5, 12
Underscore.js
Thursday, July 5, 12
Underscore.js
DocumentCloud
2009
Thursday, July 5, 12
Underscore.js
•Functional, self-contained micro library
•Uses chaining for expressiveness
•Does not inject methods into native objects!
Thursday, July 5, 12
Functional Programming
•Functions are mappings between input and output
•No side-effects
• Input A always results in output B
•No OOP
•LISP, Haskell, Erlang
Thursday, July 5, 12
Underscore.js
•_(coll).method(arg1, ..)
•_.method(coll, arg1, ..)
Thursday, July 5, 12
Underscore.jsCollections
•each•map•reduce•reduceRight•find•filter•reject•all•any•include•invoke•pluck•max•min•sortBy•groupBy•sortedIndex•shuffle•toArray•size
Arrays•first•initial•last•rest•compact•flatten•without
•union•intersection•difference•uniq•zip•indexOf•lastIndexOf•range
Functions•bind•bindAll•memoize•delay•defer•throttle•debounce•once•after•wrap•compose
Objects•keys•values•functions•extend•pick•defaults•clone•tap
•has•isEqual•isEmpty•isElement•isArray•isObject•isArguments•isFunction•isString•isNumber•isFinite•isBoolean•isDate•isRegExp•isNaN•isNull•isUndefined
Utility•noConflict•identity•times•mixin•uniqueId•escape•result•template
Chaining•chain•value
Thursday, July 5, 12
Maps function to each element in the input collection
var inp = [1, 2, 3] , out = _.map(inp, function(n){ return n*2; });
//out = [2, 4, 6]
Map
Thursday, July 5, 12
Reduces collection to a single value. mem is the initial state, each successive iteration must be returned
var inp = [1, 2, 3];
_(inp).reduce(function(mem, n){ return mem + n;});
//Iter 0: mem = 1 | n = 2//Iter 1: mem = 3 | n = 3//Returns: 6
Reduce
Thursday, July 5, 12
Iterates over a collection and extracts the values for the input key (assumes all elements in the collection are objects/arrays)
var stooges = [ {name: 'moe', age: 40} , {name: 'larry', age: 50} , {name: 'curly', age: 60}];
_.pluck(stooges, 'name');
//Returns ["moe", "larry", "curly"]
Pluck
Thursday, July 5, 12
Returns the max item in a collection.
If second argument (iterator) provided, will use to produce the value to be compared
var stooges = [ {name: 'moe', age: 40} , {name: 'larry', age: 50} , {name: 'curly', age: 60}];
_.max(stooges, function(s){ return s.age; });
//Returns {name: 'curly', age: 60}
Max (Min)
Thursday, July 5, 12
Returns the keys from a dictionary as an array
_.keys({ one: 1, two: 2, three: 3});
//Returns ["one", "two", "three"]
Keys
Thursday, July 5, 12
Maps a duplicate input dictionary on top of a predefined “default” dictionary
var iceCream = { flavor: "chocolate"};
_.defaults(iceCream, { flavor: "vanilla" , sprinkles: "lots"});
//Returns {flavor : "chocolate", sprinkles : "lots"}
Defaults
Thursday, July 5, 12
When chain is initiated, method return a self-reference back to underscore but with the value attached [similar to opening with _(val)].
The chain continues until the value is extracted using .value()
var stooges = [ {name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
var youngest = _.chain(stooges) .sortBy(function(s){ return s.age; }) .map(function(s){ return s.name + ' is ' + s.age; }) .first() .value();
//Returns "moe is 21"
Chaining
Thursday, July 5, 12
chain: begins a chain
map: takes dictionary and maps to a nested array [[key, val],[key, val], ..]
sortBy: sorts array returned by map by key (first element)
reduce: reforms an object using the nested list, [0] as key and [1] as value
value: spits out the value an ends the chain
_(request.params).chain() .map(function(v, k) { return [k,v]; }) .sortBy(function(a) { return a[0]; }) .reduce(function(s, v){ s[v[0]] = v[1]; return s; }, {}) .value();
Chain: FUN!
Thursday, July 5, 12
Backbone.js
Thursday, July 5, 12
Backbone.js
DocumentCloud
2010
Thursday, July 5, 12
Backbone.js
•Micro application framework
•Relies on jQuery/Zepto and Underscore.js
•Provides Views, Models, Collections, and Router
• If standard REST, default sync will work out of box
Thursday, July 5, 12
Model
•Fires events on value changes
•Must use model.get() and model.set()
Thursday, July 5, 12
Collection
•Collection of models
•Can be enforced
•Fires events on add, remove, reset, etc
Thursday, July 5, 12
View
•Creates own DOM object (or utilizes existing one)
•Easy event delegation/undelegation
Thursday, July 5, 12
Router
•Hash/History Router
•History management abstraction provided
Thursday, July 5, 12
Require.js
Thursday, July 5, 12
Require.js
James Burke
2009
Thursday, July 5, 12
Require.js
• Implements AMD
•Asynchronous Module Definition
•Dependency Management
Thursday, July 5, 12
r.js
•Optimizer, Compiler
•Concatenates dependencies into single file, optionally runs closure/uglifyjs/etc
Thursday, July 5, 12
Other Libraries Of Note
Thursday, July 5, 12
Compilers/Compressors
•UglifyJS• http://marijnhaverbeke.nl/uglifyjs
• JSmin:• http://www.crockford.com/javascript/jsmin.html
•YUI Compressor• http://developer.yahoo.com/yui/compressor/
http://marijnhaverbeke.nl/uglifyjs
Thursday, July 5, 12
Lawnchair
•HTML5 localstorage abstraction
•Good suite of storage adapaters
•DOM, webkit-sqlite, etc
http://brian.io/lawnchair
Thursday, July 5, 12
Moment.js
•Date/Time library
•Finally! Almost as easy as \DateTime and strtotime()
http://momentjs.com/
Thursday, July 5, 12
Enyo
•Application Framework
•Developed for the HP/Palm TouchPad
•Now open-source
•Designed for nested views and complex, finger-based UI
http://enyojs.com/
Thursday, July 5, 12
https://joind.in/6503
http://bit.ly/js-ruby-wat
Thursday, July 5, 12