How to make Ajax work for you
Upcoming SlideShare
Loading in...5
×
 

How to make Ajax work for you

on

  • 43,218 views

A three hour Ajax tutorial presented at Web 2.0 Expo Berlin on November 5th 2007.

A three hour Ajax tutorial presented at Web 2.0 Expo Berlin on November 5th 2007.

Statistics

Views

Total Views
43,218
Views on SlideShare
41,418
Embed Views
1,800

Actions

Likes
68
Downloads
2,919
Comments
0

67 Embeds 1,800

http://cfeelings.blogspot.com 1023
http://programistycznie.cba.pl 193
http://tootle.pl 178
http://cfeelings.blogspot.co.uk 54
http://cfeelings.blogspot.cz 53
http://www.slideshare.net 43
http://cfeelings.blogspot.in 22
http://cfeelings.blogspot.ca 18
http://cfeelings.blogspot.fr 14
http://cfeelings.blogspot.it 14
http://cfeelings.blogspot.com.es 13
http://lanyrd.com 12
http://cfeelings.blogspot.com.br 11
http://cfeelings.blogspot.se 10
http://onajejohnston.com 9
http://www.cfeelings.blogspot.com 8
http://practicals-javascript.blogspot.com 7
http://cfeelings.blogspot.com.ar 7
http://digitta.com 7
http://cfeelings.blogspot.de 6
http://cfeelings.blogspot.com.au 6
http://emird.blogspot.com 5
http://wildfire.gigya.com 4
http://cfeelings.blogspot.sk 4
http://techno3.blogspot.com.es 4
http://cfeelings.blogspot.mx 4
http://egox.tumblr.com 4
http://cfeelings.blogspot.jp 3
http://static.slideshare.net 3
http://techno3.blogspot.com 3
http://webcache.googleusercontent.com 3
http://www.linkist.com 3
http://dev-shopbetreiber-blog.trustedshops.de 3
http://cfeelings.blogspot.gr 3
http://cfeelings.blogspot.ru 2
http://xyydyy.blogspot.com 2
http://techno3.blogspot.in 2
http://cfeelings.blogspot.ro 2
http://translate.googleusercontent.com 2
http://www.techno3.blogspot.com.es 2
http://cfeelings.blogspot.co.at 2
http://cfeelings.blogspot.hu 2
http://maidbots.com 2
http://www.filescon.com 2
http://alpha.linkist.com 2
http://www.techno3.blogspot.com 2
http://www.ajaxfreak.com 2
http://cfeelings.blogspot.sg 1
http://eldercarerobot.com 1
http://www.isolani.co.uk 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

How to make Ajax work for you How to make Ajax work for you Presentation Transcript

  • How to make work for you Simon Willison - http://simonwillison.net/ Web 2.0 Expo Berlin 5th November 2007
  • In this talk • Where Ajax came from • When you should (and shouldn’t) use it • Ajax fundamentals (including a DOM and JavaScript refresher) • Advanced Ajax techniques • Picking and using a JavaScript library
  • Please ask questions at any time
  • February 2005
  • AJAX v.s. Ajax “Asynchronous JavaScript + XML”
  • AJAX v.s. Ajax “Any technique that “Asynchronous allows the client to JavaScript + XML” retrieve more data from the server without reloading the whole page”
  • Why did Ajax happen? • Two reasons: • The browsers that mattered all added support for IE’s XMLHttpRequest object (which IE has had since 1998) • Jesse James Garrett came up with a name that sucked a lot less than “XMLHttpRequest” did
  • Pre-Ajax... • “Remote Scripting” (not as catchy) • Various unpleasant but ingenious hacks: • Scriptable Java applets • Passing data through changes to a cookie • Passing data through a hidden iframe • (That one’s actually still in use)
  • Ajax scenarios
  • Some anti-patterns • Drag and drop shopping carts • Massive page updates e.g. pagination • Unlinkable content (see also bookmarking) • Breaking browser expectations • Forgetting the loading icon!
  • Fundamentals
  • The three legged stool (X)HTML CSS JavaScript
  • The three legged stool The DOM (X)HTML CSS JavaScript
  • The DOM
  • The DOM
  • The DOM <html> <head> <body> <title> <div id=quot;headquot;> <div id=quot;mainquot;> <h1> <p> <p> <p>
  • Key DOM methods • document.getElementsByTagName, document.getElementById • el.childNodes, el.parentNode, el.firstChild, el.nextSibling, el.getAttribute • el.appendChild, el.insertBefore, el.setAttribute, el.removeChild • document.createElement, document.createTextNode http://www.howtocreate.co.uk/tutorials/javascript/domstructure
  • JavaScript doesn’t suck! • Just remember; your; semicolons; • Avoid accidental globals: always declare your variables with “var” • Take the time to figure out higher order programming, where you treat functions as objects
  • CSS class switching • Often if you are dynamically making large- scale changes to the layout of a page... • ... you can do most of the work by defining an alternative CSS class ... • ... and then switching a container element’s className property in your JavaScript
  • Firebug!
  • Firebug • Inspect HTML elements to see what CSS rules currently apply to them • Interactive console for experimenting with JavaScript against the loaded page • Full JavaScript debugger, including breakpoints • Profile your code and your site’s assets and Ajax requests • Logging with console.log() and friends
  • XMLHttpRequest • The object that lets you make HTTP requests from within JavaScript • IE had it first, using an ActiveX Object • Almost nothing to do with XML • Asynchronous (so you use callbacks)
  • XMLHttpRequest • The object that lets you make HTTP requests from within JavaScript • IE had it first, using an ActiveX Object • Almost nothing to do with XML • Asynchronous (so you use callbacks)
  • var xhr = createXHR(); xhr.onreadystatechange = onComplete; xhr.open('GET', '/helloworld.txt', true); xhr.send(null); function onComplete() { if (xhr.readyState == 4) { if (xhr.status == 200) { alert(xhr.responseText); } else { alert('Error code ' + xhr.status); } } }
  • var xhr = createXHR(); xhr.onreadystatechange = onComplete; xhr.open('GET', '/helloworld.txt', true); xhr.send(null); function onComplete() { if (xhr.readyState == 4) { if (xhr.status == 200) { alert(xhr.responseText); } else { alert('Error code ' + xhr.status); } } }
  • var xhr = createXHR(); xhr.onreadystatechange = onComplete; xhr.open('GET', '/helloworld.txt', true); xhr.send(null); function onComplete() { if (xhr.readyState == 4) { if (xhr.status == 200) { alert(xhr.responseText); } else { alert('Error code ' + xhr.status); } } }
  • var xhr = createXHR(); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status == 200) { alert(xhr.responseText); } else { alert('Error code ' + xhr.status); } } }; xhr.open('GET', '/helloworld.txt', true); xhr.send(null);
  • function createXHR() { var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } return xhr; }
  • function createXHR() { var xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { try { xhr = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } return xhr; }
  • var xhr = createXHR(); xhr.onreadystatechange = onComplete; xhr.open('POST', '/helloworld.php', true); xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' ); xhr.send('name=Simon&age=26');
  • xhr.open('POST', '/helloworld.php', true); The third argument specifies that we want to make an asynchronous request (“tell me when you’re done by calling this function”). If you set this to false you’ll get a synchronous request, which will completely hang the browser until the request returns. Don’t do that.
  • Too much boilerplate? • That’s quite a lot to remember • Best option: don’t remember any of it! • Use a good library instead • Lots more on those later on
  • doRequest doRequest(quot;GETquot;, quot;/blah.txtquot;, null, function(xhr) { doSomethingWith(xhr.responseText); }); doRequest(quot;GETquot;, quot;/getinfo.phpquot;, { quot;namequot;: quot;Simonquot; }, function(xhr) { doSomethingWith(xhr.responseText); }); doRequest(quot;POSTquot;, quot;/getinfo.phpquot;, { quot;namequot;: quot;Simonquot; }, function(xhr) { doSomethingWith(xhr.responseText); });
  • function doRequest(method, url, args, callback) { var xhr = createXHR(); method = method.toUpperCase(); args = args && buildQueryString(args); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { callback(xhr); } }; if (method == 'GET' && args) { url += '?' + args; args = null; } xhr.open(method, url, true); if (method == 'POST') { xhr.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' ); } xhr.send(args); }
  • function buildQueryString(obj) { var bits = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { bits[bits.length] = escape(key) + '=' + escape(obj[key]); } } return bits.join('&'); } var s = buildQueryString({ name: 'Simon', age: 26 }); name=Simon&age=26
  • Data transport options
  • Client data submission • Requests can have anything you like in the body: • HTML, XML, JSON... • So if you really want to, you can access SOAP or XML-RPC services from JavaScript • For almost all purposes, regular form arguments suffice • REST APIs are a good fit as well
  • Server responses • Plain text • HTML fragments • CSV or similar • XML • Executable JavaScript • JSON
  • Plain text • Just sending back a simple value • xhr.responseText is all you need • Pros: • Absurdly simple • Cons: • Only supports a single value or string
  • HTML fragments • Return an HTML fragment, and inject it using innerHTML function onSuccess(xhr) { var div = document.getElementById('response'); div.innerHTML = xhr.responseText; } <div id=quot;responsequot;> </div>
  • Fragment pros and cons • Pros: • Again, really simple • You can leverage existing server-side templates and techniques • Cons: • You have to change your server-side code to change client-side behaviour • You can't reuse your endpoint
  • Executable JavaScript • We can pass JavaScript code back from the server and execute it directly document.getElementById( 'response').innerHTML = 'Done!'; function onSuccess(o) { eval(o.responseText); }
  • • Pros: • Incredibly simple client-side code • The server can do abolutely anything, without needing to modify the client-side code • Cons: • Weird factoring of code - dynamically generating code to run on the client makes it hard to keep track of the big picture • How about just sending structured data?
  • CSV or similar • We want structured data! Simon Willison,26,simon@simonwillison.net • Pros: • Easy to parse: xhr.responseText.split(','); • Cons: • How do we pass values containing commas? • Index based, so brittle and hard to maintain
  • XML • Surely XML will save us! <person> <name>Simon</name> <age>26</age> </person> function onSuccess(xhr) { var dom = xhr.responseXML; showPerson( dom.getElementsByTagName('name')[0].data, parseInt(dom.getElementsByTagName('age')[0].data, 10) }); }
  • XML pros and cons • Pros: • We can re-use our DOM knowledge • xhr.responseXML parses it for us • We can call existing Web Services directly • Cons: • Verbose handling code • Is this the simplest thing that could possibly work?
  • JSON • A standard for representing common data structures, quot;discoveredquot; by Douglas Crockford • Common data structures? • Associative arrays (dictionaries / hashes) • Arrays (lists) • Numbers, strings, booleans • A subset of JavaScript syntax
  • JSON example {quot;namequot;: quot;Simonquot;, quot;agequot;: 26} function onSuccess(xhr) { var person = eval('(' + xhr.responseText + ')') ... )
  • More complex JSON {quot;peoplequot;: [{ quot;namequot;: quot;Simonquot;, quot;emailquot;: quot;simon@simonwillison.netquot; }, { quot;namequot;: quot;Nataliequot;, quot;emailquot;: quot;nat@natbat.netquot; } ]} function onSuccess(xhr) { var people = eval('(' + xhr.responseText + ')'); ... }
  • To compare... <people> <person> <name>Simon</name> <email>simon@simonwillison.net</email> </person> <person> <name>Natalie</name> <email>nat@natbat.net</email> </person> </people>
  • To compare... function onSuccess(o) { var dom = o.responseXML; var people = []; var people_els = dom.getElementsByTagName('people'); for (var i = 0, el; el = people_els[i]; i++) { people[people.length] = { 'name': el.getElementsByTagName('name')[0].data, 'email': el.getElementsByTagName('email')[0].data }; } ... }
  • JSON v.s. XML JSON XML Bytes (excluding whitespace) 95 156 Lines of code to process 1 7+
  • It ain’t just for JavaScript • Libraries for consuming and generating JSON are available for many languages, including: • Python • Ruby • PHP • Java ... • JSON works really well as a general purpose tool for exchanging data structures
  • Aside: XSLT • Modern browsers support XSLT transforms - albeit with differing APIs • These can be significantly faster than regular DOM manipulation • If you're having performance problems, this may be worth looking in to
  • Recommendations • For quick and simple apps, HTML fragments offer the path of least resistance • For most purposes, JSON makes the most sense • Use XML if you already have an XML Web Service that you want to consume (or you need an XSLT speed boost)
  • Let’s see some running code
  • Advanced Ajax topics
  • Cross-domain Ajax
  • The same-origin restriction • XMLHttpRequest is only allowed to communicate with the domain from which the page was loaded • The same is true of JavaScript calls between windows, frames and iframes • This is a critical browser security feature
  • The intranet attack • http://wiki.private.corp/ contains private data • User is tricked in to visiting evilexample.com • evilexample.com uses XMLHttpRequest (or a hidden iframe child) to load and steal data from http://wiki.private.corp/
  • • JSON-P offers a (hackish) solution to the cross-domain XMLHttpRequest restriction http://example.com/query?name=Simon callback({quot;namequot;: quot;Simonquot;, quot;agequot;: 26}); function loadJSON(url) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; document.getElementsByTagName('head')[0].appendChild(script); } function callback(person) { ... } loadJSON('http://example.com/query?name=' + name);
  • • JSON-P offers a (hackish) solution to the cross-domain XMLHttpRequest restriction http://example.com/query?name=Simon callback({quot;namequot;: quot;Simonquot;, quot;agequot;: 26}); function loadJSON(url) { var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; document.getElementsByTagName('head')[0].appendChild(script); } function callback(person) { ... } loadJSON('http://example.com/query?name=' + name);
  • Pros and cons • Pros: • Lets you call services hosted on other domains, provided they opt-in • del.icio.us, Flickr, other sites offer this • Cons: • Detecting errors is harder than with XMLHttpRequest • You have to trust the site who’s code you are executing
  • XSS
  • • XSS attacks occur when a malicious third party injects untrusted code (HTML, CSS or JavaScript) in to your page • It’s generally a server-side consideration, but you need to take it in to consideration when writing JavaScript as well • Ajax can compound the problem by allowing users to create self-propagating “worms”
  • CSRF
  • CSRF for GET <img src=quot;http://example.com/admin/delete.php?id=5quot;> Trick someone who is signed in to example.com/admin/ in to visiting a page hosting that image and you’ll force them to delete something.
  • CSRF for POST <form id=quot;evilquot; action=quot;http://example.com/admin/delete.phpquot; method=quot;POSTquot;> <input type=quot;hiddenquot; name=quot;idquot; value=quot;5quot;> </form> <script> document.getElementById('evil').submit() </script>
  • CSRF protection • For regular forms, add a hidden field with a one-time secret token and check for that token on every submission • For Ajax, either do the above or use: xhr.setRequestHeader( quot;X-Requested-Withquot;, quot;XMLHttpRequestquot; );
  • Unobtrusive JavaScript
  • Unobtrusive JavaScript • JavaScript isn't always available • Security conscious organisations (and users) sometimes disable it • Some devices may not support it (mobile phones for example) • Assistive technologies (screen readers) may not play well with it • Search engine crawlers won't execute it • Unobtrusive: stuff still works without it!
  • Progressive enhancement • Start with solid markup • Use CSS to make it look good • Use JavaScript to enhance the usability of the page • The content remains accessible no matter what
  • Adding events • Unobtrusive JavaScript relies on adding event handlers after the fact • The naive way of doing this: window.onload = function() { for (var i = 0, link; link = document.links[i]; i++) { if (link.className == 'external') { link.onclick = function() { window.open(this.href); return false; } } } };
  • Problem • If you later assign something else to window.onload (or one of the link.onclicks) you will clobber your behaviour • You should add events quot;properlyquot;... • Different in different browsers • attachEvent v.s. addEventListener • My advice: use a library!
  • Unobtrusive examples
  • labels.js • One of the earliest examples of this technique, created by Aaron Boodman (now of Greasemonkey and Google Gears fame)
  • How it works <label for=quot;searchquot;>Search</label> <input type=quot;textquot; id=quot;searchquot; name=quot;qquot;> • Once the page has loaded, the JavaScript: • Finds any label elements linked to a text field • Moves their text in to the associated text field • Removes them from the DOM • Sets up the event handlers to remove the descriptive text when the field is focused • Clean, simple, reusable
  • easytoggle.js • An unobtrusive technique for revealing panels when links are clicked <ul> <li><a href=quot;#panel1quot; class=quot;togglequot;>Panel 1</a></li> <li><a href=quot;#panel2quot; class=quot;togglequot;>Panel 2</a></li> <li><a href=quot;#panel3quot; class=quot;togglequot;>Panel 3</a></li> </ul> <div id=quot;panel1quot;>...</div> <div id=quot;panel2quot;>...</div> <div id=quot;panel3quot;>...</div>
  • How it works • When the page has loaded... • Find all links with class=quot;togglequot; that reference an internal anchor • Collect the elements that are referenced by those anchors • Hide all but the first • Set up event handlers to reveal different panels when a link is clicked • Without JavaScript, links still jump to the right point
  • Django filter lists • Large multi-select boxes aren't much fun • Painful to scroll through • Easy to lose track of what you have selected • Django's admin interface uses unobtrusive JavaScript to improve the usability here
  • • Ajax is often used to avoid page refreshes • So... • Write an app that uses full page refreshes • Use unobtrusive JS to quot;hijackquot; links and form buttons and use Ajax instead • Jeremy Keith coined the term quot;Hijaxquot; to describe this
  • More progressive Ajax suggestions • Live search / filtering • Adding comments / tags • Smart form validation • Checking if usernames are already taken • You could even make a progressively enhanced chat room
  • The onload problem • All of these examples use code that runs when the window quot;loadquot; event is fired • Wait until page is loaded, then manipulate the DOM • Problem: If the page takes a while to load (large inline images) there will be a Flash Of Unstyled Content (FOUC) • Also, if the user clicks things before the setup code has fired they won't get the expected behaviour.
  • document.write(css) • If the effect requires hiding some otherwise visible elements, you can document.write a stylesheet <script type=quot;text/javascriptquot;> document.write('<style type=quot;text/cssquot;>'; document.write('.hideme { display: none }'); document.write('</style>'); </script>
  • body.onclick • If your effect is triggered by the user clicking on something, attach code to the document.body quot;clickquot; event right at the start of your code (no need to wait for the document quot;loadquot; event) YAHOO.util.Event.on(document.body, 'click' function(e) { var clicked_el = YAHOO.util.Event.getTarget(e); // ... }
  • onDOMReady • A number of attempts have been made to create an onDOMReady event that fires when the DOM has been constructed but before the page has loaded • dean.edwards.name/weblog/2006/06/again/ • Modern libraries all support this in some form • Problem: CSS may not have loaded, so calculated dimensions may be incorrect
  • • Unobtrusive JavaScript is the Right Way to go about things, but runs in to browser differences even faster than regular JavaScript • Which leads us neatly on to...
  • Frameworks and Libraries
  • JavaScript libraries • ajaxpatterns.org lists over 40 general purpose JavaScript libraries • ... and that’s not including the many libraries tied to a specific server-side language • Why are there so many of them?
  • “The bad news: JavaScript is broken. The good news: It can be fixed with more JavaScript!” Geek folk saying
  • • Inconsistent event model (thanks, IE) • Positioning and co-ordinates • Memory management (thanks, IE) • The DOM is a horrible API! • JavaScript-the-language has quite a few warts • But it’s powerful enough to let you fix them • Classes and inheritance can be confusing • Many useful JS utility functions are missing • Drag and drop and Animation are really hard
  • Narrowing them down... • Prototype (and Scriptaculous) • The Yahoo! User Interface Library - YUI • jQuery • The Dojo Toolkit
  • Honourable mentions • MochiKit • No updates since early 2006 • The Google Web Toolkit • I don’t do Java • mooTools • Lots of buzz, but I haven’t figured out why yet
  • Download Get the latest version—1.5.1 Learn Prototype is a JavaScript Framework that aims to Online documentation and resources. ease development of dynamic web applications. Discuss Featuring a unique, easy-to-use toolkit for class-driven development and the nicest Ajax library around, Prototype Mailing list and IRC is quickly becoming the codebase of choice for web application developers everywhere. Contribute Submit patches and report bugs. Prototype and Scriptaculous Prototype and script.aculo.us: The quot;Bungee bookquot; has landed! Who's using Prototype? Meet the developers Core team member Christophe Porteneuve has been hard at work for the past few months tracking
  • • Prototype focuses on basic browser compatibility and JavaScript language enhancement • Tries to make JavaScript more like Ruby • Extends most of JavaScript’s built-in objects with new functionality • Scriptaculous adds fancy effects, basic widgets and drag and drop
  • $$('#bmarks li').each(function(li){ Event.observe(li, 'click', function(e) { this.style.backgroundColor = 'yellow'; }.bindAsEventListener(li)); });
  • The Yahoo UI Library
  • • Created at Yahoo!, BSD licensed • Designed for both creating new applications and integration with legacy code • Focused on browser issues; almost no functionality relating to JS language itself • Extensively tested and documented
  • controls calendar container autocomplete menu slider treeview dragdrop animation dom event connection utilities
  • YAHOO.util.Event.on(window, 'load', function() { var div = YAHOO.util.Dom.get('messages'); setTimeout(function() { var anim = new YAHOO.util.Anim(div, { height: {to: 0}, opacity: {to: 0} }, 0.4); anim.animate(); anim.onComplete.subscribe(function() { div.parentNode.removeChild(div); }); }, 2000); });
  • Common YUI idiom $E = YAHOO.util.Event; $D = YAHOO.util.Dom; $E.on(window, 'load', function() { var div = $D.get('messages'); ... });
  • jQuery
  • jQuery(function($) { $(quot;a.hidemequot;). css('color', 'red'). click(function() { $(this).hide(quot;slowquot;); return false; }); });
  • • Simple philosophy: find some nodes, then do something to them • Minimal impact on your global namespace - it adds two global symbols: jQuery and $, and $ can be easily reverted • API designed around “chaining” - other libraries are now emulating this • Outstanding node selection, based on CSS 3 and custom extensions • Small core library with an intelligent plugin mechanism
  • Dojo
  • • The oldest of the current popular libraries, pre-dating even Ajax • Incredible amounts of functionality • Used to suffer from a tough learning curve, although the 0.9 release simplifies things greatly
  • Dojo components • dojo • Core library, similar to jQuery etc • Smart package managment with dynamic code loading • dijit • Advanced widget system • dojox • Dojo eXperimental - crazy voodoo magic
  • dijit
  • <div dojoType=quot;dijit.layout.TabContainerquot; sizeShare=quot;40quot;> <div id=quot;tab1quot; dojoType=quot;dijit.layout.ContentPanequot; title=quot;Form Feelquot;> <h2>Various Form Elements:</h2> <form name=quot;dijitFormTestquot;> <p><input type=quot;checkBoxquot; dojoType=quot;dijit.form.CheckBoxquot; checked=quot;checkedquot;> Standard Dijit CheckBox <br><input type=quot;checkBoxquot; dojoType=quot;dijit.form.CheckBoxquot; disabled=quot;disabledquot;> Disabled Dijit <br> <input type=quot;checkBoxquot; dojoType=quot;dijit.form.CheckBoxquot; disabled=quot;disabledquot; checked=quot;checkedquot;> Checked and Disabled Dijit </p> ...
  • dojox
  • • Graphics (cross-browser drawing API) • Offline storage • Cryptography • Templating • Data grids and more • “The future of the browser today”
  • My library selection criteria • Enables unobtrusive JavaScript • Plays well with other code • Smart use of namespacing • Global variable impact kept to a minimum • Tie breaker: the less code I have to write the better!
  • • I’m currently using and recommending jQuery for most situations • But... there’s cut-throat competition between the various libraries at the moment • This is one of the reasons I care about interoperability - commit to a single library and you might lose out when one of the others jumps ahead of it
  • The law of leaky abstractions
  • http://www.joelonsoftware.com/articles/LeakyAbstractions.html My interpretation: The more you rely on abstractions, the worse off you’ll be when one of them leaks
  • Thank you!