Upgrade to Pro — share decks privately, control downloads, hide ads and more …

HTML5 and JavaScript Part Deux: JavaScript

HTML5 and JavaScript Part Deux: JavaScript

Second-half of the full-day tutorial "HTML5 And JavaScript" at php|tek 2012

Daniel Cousineau

May 22, 2012
Tweet

More Decks by Daniel Cousineau

Other Decks in Programming

Transcript

  1. "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
  2. parseInt("56"); //56 parseInt("42.567"); //42 parseInt("asdf"); //NaN parseInt("5a6"); //5 parseFloat("24.68"); //24.68

    parseFloat("asdf"); //NaN parseFloat("24a"); //24 String to Number Thursday, July 5, 12
  3. 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
  4. var object = { foo: 'value', 'complex key': 0, bar:

    { nested: true } }; object.foo; //'value' object.['complex key']; //0 object.bar.nested; //true object.bar['nested']; //true object['bar'].nested; //true object['bar']['nested']; //true Objects Thursday, July 5, 12
  5. in or hasOwnProperty() •Tough call: •.hasOwnProperty() more consistent •in checks

    inherited properties •Used in for loop Thursday, July 5, 12
  6. 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
  7. Arrays •Special object •Numerical keys only •Keeps intrinsic ordering •Short

    ([]) and Long (new Array()) syntax Thursday, July 5, 12
  8. 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
  9. var arr = [1,2,3,4,6]; arr.indexOf(2); //1 arr.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
  10. delete •Removes element from an object •“Removes element from an

    array” •Not really, just sets it to undefined Thursday, July 5, 12
  11. 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
  12. function Foo() { //... } Foo(); //valid Bar(); //valid function

    Bar() { //... } Functions Thursday, July 5, 12
  13. function Foo() { } Foo.bar = "value"; 'bar' in Foo;

    //true Foo.bar == "value"; //true Functions Thursday, July 5, 12
  14. 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
  15. arguments •A special variable found inside a function •A not-quite

    array object containing all the function arguments Thursday, July 5, 12
  16. 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
  17. 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
  18. 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
  19. 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 DOM Thursday, July 5, 12
  20. 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
  21. function Foo() { var count = 0; return function() {

    count = count + 1; return count; }; } var bar = Foo(); bar(); //1 bar(); //2 bar(); //3 Closures Thursday, July 5, 12
  22. function createAdder(amount) { return function(input) { return input + amount;

    }; } var add2 = createAdder(2); add2(2); //4 add2(8); //10 var add3 = createAdder(3); add3(3); //6 add3(7); //10 Closures Thursday, July 5, 12
  23. (function(exports, undefined){ //ALL your code here var localVar = "bar"

    globalVar = "baz"; exports.foo = "bat"; })(window); alert(localVar); //error alert(globalVar); //"baz" alert(window.globalVar); //"baz" alert(foo); //"bat" alert(window.foo); //"bat" Module Pattern BEWARE: export (singular) is a reserved word in Safari Thursday, July 5, 12
  24. 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
  25. var outerScope = 10; var outerScope2 = 10; function Foo()

    { var outerScope = 20; var innerScope = 20; globalVariable = 30; outerScope2 = 40; } Foo(); alert(outerScope); //10 alert(outerScope2); //40 alert(innerScope); //error alert(globalVariable); //30 Global & Local Thursday, July 5, 12
  26. function Foo() { var baz = 1; function Bar() {

    return baz; } return Bar(); } Foo(); //1 Lexical Scoping function Foo() { var baz = 1; return Bar(); } function Bar() { return baz; } Foo(); //baz is not defined Thursday, July 5, 12
  27. 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
  28. function makeAdder(a) { return function(b) { return a+b; } }

    var two = makeAdder(2); two(1); //3 two(2); //4 two(3); //5 Practical: Currying Thursday, July 5, 12
  29. 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
  30. 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
  31. var Foo = { bar: "bar", baz: function() { return

    this.bar; } }; Foo.bat = function() { return this.bar + "bat"; }; Foo.bat(); //"barbat" this Thursday, July 5, 12
  32. call & apply •Methods in the function prototype •Change the

    context in which a function executes! Thursday, July 5, 12
  33. 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
  34. try { funcDoesNotExist(); } catch (e) { alert(e); //ReferenceError: funcDoesNotExist

    is not defined } finally { //Always Executes } Exceptions Thursday, July 5, 12
  35. 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
  36. 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
  37. 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
  38. instance ‣ __proto__ ‣ baz ‣ constructor ‣ __proto__ ‣

    ... var instance = new Foo(); instance.baz(); //works instance.bar(); //error Foo.bar(); //works Foo.baz(); //error Foo.prototype.baz(); //works new Thursday, July 5, 12
  39. instance ‣ bat ‣ __proto__ ‣ baz ‣ constructor ‣

    __proto__ ‣ ... instance.bat = function() { /* ... */ } instance.bat(); //works Foo.bat(); //error Foo.prototype.bat(); //error new Thursday, July 5, 12
  40. 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(); //1 foo2.bar(); //2 Foo.prototype.bar = function() { return this.baz * 2; }; foo1.bar(); //2 foo2.bar(); //4 Overriding Prototype Thursday, July 5, 12
  41. var id = setInterval(function() { //Code to execute every 1000

    milliseconds }, 1000); //clearInterval(id); to stop setInterval Thursday, July 5, 12
  42. var id = setTimeout(function() { //Code to execute after 1000

    milliseconds have passed }, 1000); //clearTimeout(id); to cancel setTimeout Thursday, July 5, 12
  43. 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
  44. Basic selection methods in native DOM document .getElementById('foo'); document .getElementsByClassName('.bar');

    document .getElementsByTagName('script'); DOM: Selection Thursday, July 5, 12
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. Coding Styles •Mostly your standard C based style techniques •Special

    considerations •Semi-colons? No semi-colons? •Leading , ? •Prototype Definition? Thursday, July 5, 12
  52. var dict = { foo: 'bar', baz: 'bat' }; var

    dict = { foo: 'bar' , baz: 'bat' }; Comma Style Thursday, July 5, 12
  53. var foo; var bar; var baz; var foo , bar

    , baz; var Declaration Style Thursday, July 5, 12
  54. function Foo() { } Foo.prototype.bar = function(){ }; Prototype Style

    function Foo() { } Foo.prototype = { bar: function() { } } Thursday, July 5, 12
  55. 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
  56. 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
  57. 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(); //success bar(); //not found! IIFE Thursday, July 5, 12
  58. Pro-Tip •Create an application namespace as a dictionary in the

    global scope •Add in any global level configuration values Thursday, July 5, 12
  59. 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
  60. {"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
  61. 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
  62. Selectors •$('selector') returns jQuery object for chaining purposes •Chained methods

    will apply to all results if selector matches multiple elements Thursday, July 5, 12
  63. 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
  64. Gets the value of the selected option in a select

    box $('select option:selected').val(); Selectors Thursday, July 5, 12
  65. Tests matched element against selector, in this case the jQuery

    ‘visible’ selector $('.foo').is(':visible'); Testing Elements Thursday, July 5, 12
  66. Custom Filters •jQuery provides the ability to create custom filters

    •:radio, :hidden, etc are custom filters provided by default Thursday, July 5, 12
  67. Chaining •Most all jQuery methods are chain-able •If $() returns

    > 1 element, methods invoked will apply to all matched Thursday, July 5, 12
  68. 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
  69. Events •jQuery wraps an event handling system •Handles browser events,

    AJAX events, and custom events Thursday, July 5, 12
  70. $(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
  71. 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
  72. 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
  73. 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
  74. 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
  75. 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
  76. 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
  77. 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
  78. 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
  79. 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
  80. Insertion (inside): -append -appendTo -html -prepend -prependTo -text Insertion (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
  81. 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
  82. 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
  83. 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
  84. $.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
  85. 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
  86. (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
  87. 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
  88. Underscore.js Collections •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
  89. 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
  90. 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
  91. 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
  92. 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
  93. 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
  94. 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
  95. 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
  96. 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
  97. 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
  98. View •Creates own DOM object (or utilizes existing one) •Easy

    event delegation/undelegation Thursday, July 5, 12
  99. Lawnchair •HTML5 localstorage abstraction •Good suite of storage adapaters •DOM,

    webkit-sqlite, etc http://brian.io/lawnchair Thursday, July 5, 12
  100. Moment.js •Date/Time library •Finally! Almost as easy as \DateTime and

    strtotime() http://momentjs.com/ Thursday, July 5, 12
  101. 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