460 likes | 505 Views
Learn about unobtrusive JavaScript, a method used to separate behavior from content and style, to create usable and maintainable web sites. Explore different libraries for implementing unobtrusive JavaScript and see examples of how they can be compared in terms of performance, code base, and documentation.
E N D
JavaScript Library Showdown Rob Larsen 7.14.2009 htmlcssjavascript.com | @rob_react htmlcssjavascript.com /downloads/libraries.ppt
Who is this Guy Anyway? • 10+ years HTML/CSS/JavaScript all day • Principal Presentation Engineer at Cramer • PAST: AdvisorTech, Compete, Demandware, Boston's Weekly Dig, Gillette, Museum of Science, Boston, PC Connection, State Street, Webex
History • I remember when dHTML was “cool” document.all(“ftw”) document.layers[0]
History • And then it wasn’t (http://www.amazon.com/Macromedia-Flash-5-Upgrade-Windows/dp/B00004WG0L)
History • And then it was actually cool, but we stopped mentioning dHTML Photo by Martin Kliehm ( http://www.flickr.com/photos/martin-kliehm/536545606/ )
Perspective • Front end performance • Library agnostic
What Libraries? • “By the book” JavaScript • “What I Would Normally Do” (small library with basic x-browser features and nothing else) • Dojo • jQuery • Prototype/Scriptaculous • YUI
Concept • “I’ve got how long to finish this?” • Let’s see what’s out there…
How Will They Be Compared? • Simple Tasks • Performance (Page render & execution) • Code Base • Documentation/Overall Presentation • Anecdotes
What Tasks? • Unobtrusive JavaScript • Fire a function when the DOM is loaded • That function attaches a click event to an HTML element • When clicked, a function fires that: • Grabs an RSS feed from Reddit and writes it into a UL • Grabs a JSON feed from search.twitter.com and writes it into a UL • Creates an IMG, inserts it into the document and Fades it up from 0 opacity.
Unobtrusive JavaScript? What is it? • Unobtrusive JavaScript is a method used to separate behavior from content and style, into its own discrete component. • Helps create usable, maintainable web sites
Unobtrusive JavaScript? Why? • Once coded, it should be easy to implement • It's accessible • The HTML markup is kept lean • Easier maintenance
Unobtrusive JavaScript? How does it work? • Separate structure, style and behavior • Specifcally No inline event handlers • No, REALLY. No inline event handlers. • Seriously. <a href=“#” onclick=“woot()”> is bad • Based on structure, attach events
* • “Not Science” the numbers are for discussion, not for library turf wars • Get it done • Shallow, not deep • Obvious answers- didn’t phone a friend
Exciting? • Heck Yeah. Photo by ortizmj12 (http://www.flickr.com/photos/23912576@N05/2940137084/) Photo by laverrue (http://www.flickr.com/photos/23912576@N05/2940137084/)
Let’s Look at Some Code http://htmlcssjavascript.com/samples/presentation/
HTML <html> <head> <title>JavaScript</title> <script type="text/javascript" src="scripts/base.js"></script> <style type="text/css" media="screen"> @import url("../_assets/styles/screen.css"); </style> </head> <body> <div id="container"> <h1>Tell me about <a href="http://www.google.com/search?q=javascript" id="make-it-so">JavaScript</a></h1> <div id="twitter"> <!—tweets go here--> </div> <div id="feed"> <!—reddit goes here--> </div> <div id="image"> <!--image goes here--> </div> </div> </body> </html>
Add Load Event/ Add Event JavaScript function init() { document.getElementById("make-it-so").addEventListener("click" , results, false); } window.addEventListener("DOMContentLoaded", init, false); Dojo dojo.addOnLoad( function() { dojo.connect(dojo.byId("make-it-so"), 'onclick', results) } ); jQuery $(document).ready( function() { $("#make-it-so").click(results); } );
Add Load Event/ Add Event Prototype document.observe("dom:loaded", function() { $("make-it-so").observe("click" , results, false); }); YUI function init() { YAHOO.util.Event.addListener(YAHOO.util.Dom.get("make-it-so"), "click", results, this); }; YAHOO.util.Event.onDOMReady(init);
Add Load Event/ Add Event WIWND //Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/ function init() { if (arguments.callee.done) return; arguments.callee.done = true; if (_timer) clearInterval(_timer); //demo addEvent(document.getElementById("make-it-so"), "click" , results ); //end demo }; if (document.addEventListener) { document.addEventListener("DOMContentLoaded", init, false); }; //http://javascript.nwbox.com/IEContentLoaded/ /*@cc_on @*/ /*@if (@_win32) (function () { try { document.documentElement.doScroll('left'); } catch (e) { setTimeout(arguments.callee, 50); return; } init(); })(); /*@end @*/ if (/WebKit/i.test(navigator.userAgent)) { // sniff var _timer = setInterval(function() { if (/loaded|complete/.test(document.readyState)) { init(); // call the onload handler } }, 10); }; window.onload = init;
Get JSON JavaScript/WIWND var twitterJSON = document.createElement("script"); twitterJSON.type="text/javascript"; twitterJSON.src="http://search.twitter.com/search.json?callback=writeTwitterSearchResults&q=%23javascript&count=10"; document.body.appendChild(twitterJSON); Dojo dojo.xhrGet( { url: '../json.php?url=http://search.twitter.com/search.json?q=javascript&count=10', handleAs: "json", load: function(responseObject, ioArgs) { writeTwitterSearchResults(responseObject) } }); jQuery $.getJSON("../json.php?url=http://search.twitter.com/search.json?q=javascript&count=10", writeTwitterSearchResults );
Get JSON Prototype New Ajax.Request('../json.php?url=http://search.twitter.com/search.json?q=javascript&count=10', { method:'get', requestHeaders: {Accept: 'application/json'}, onSuccess: function(transport){ var json = transport.responseText.evalJSON(true); writeTwitterSearchResults(json); } } ); YUI YAHOO.util.Get.script("http://search.twitter.com/search.json?callback=writeTwitterSearchResults&q=%23javascript&count=10");
XHR JavaScript getData : function() { var data = new XMLHttpRequest(); data.onreadystatechange = function(){ if ( data.readyState == 4 && data.responseXML != null) { reddit.parseIt(data.responseXML); } }; data.open("GET", "../feed.php?url=http://www.reddit.com/r/javascript/.rss", true); data.send(null); } Dojo dojo.xhrGet( { url: '../feed.php?url=http://www.reddit.com/r/javascript/.rss', handleAs: "xml", load: function(responseObject, ioArgs) { reddit(responseObject) } });
XHR jQuery $.get("../feed.php?url=http://www.reddit.com/r/javascript/.rss", reddit ); Prototype new Ajax.Request("../feed.php?url=http://www.reddit.com/r/javascript/.rss", { method: 'get', onSuccess: function(transport) { reddit(transport.responseXML) } }); YUI var callback = { success:reddit }; var request = YAHOO.util.Connect.asyncRequest('GET', "../feed.php?url=http://www.reddit.com/r/javascript/.rss", callback);
Remove Element JavaScript twitterDIV.removeChild(document.getElementById("twitter-list")); WIWND twitterDIV.innerHTML=""; Dojo dojo.destroy("twitter-list"); jQuery $("#twitter-list").remove(); Prototype $("twitter-list").remove(); YUI twitterDIV.removeChild(YAHOO.util.Dom.get("twitter-list"));
Add Element, Fade Up JavaScript var image = { insert : function(){ if (document.getElementById("fadeMe")) { document.getElementById("image").removeChild(document.getElementById("fadeMe")); } var newImage = document.createElement("img"); newImage.src= "/web/samples/presentation/_assets/images/javascript.jpg"; newImage.setAttribute("id","fadeMe"); newImage.style.opacity=0; document.getElementById("image").appendChild(newImage); image.fadeUp(); }, fadeUp : function() { var fadeImage = document.getElementById("fadeMe") if (fadeImage.style.opacity < 1 ) { fadeImage.style.opacity=parseFloat(fadeImage.style.opacity) + .05; var callback = function() { image.fadeUp(); } setTimeout(callback,50); } } }
Add Element, Fade Up Dojo var newImage = document.createElement("img"); newImage.src= "/web/samples/presentation/_assets/images/javascript.jpg"; newImage.setAttribute("id","fadeMe"); newImage.style.opacity=0; dojo.byId("image").appendChild(newImage); dojo.fadeIn({ node : "fadeMe" , duration : 3000 }).play(); jQuery $("#image").append("<img id='fadeMe' src='/web/samples/presentation/_assets/images/javascript.jpg' style='display:none' />"); $("#fadeMe").fadeIn("slow"); Prototype $("image").insert(new Element("img", {"src" : "/web/samples/presentation/_assets/images/javascript.jpg", "id" :"fadeMe", "style" : "display:none"})); $("fadeMe").appear({ duration: 3.0 });
Add Element, Fade Up WIWND var image = { insert : function(){ if ($("fadeMe")) { $("image").innerHTML=""; }; /*@cc_on /*@if (@_win32) var style= "filter:alpha(opacity=0)"; @else @*/ var style="opacity:0"; /*@end @*/ $("image").innerHTML="<img src='/web/samples/presentation/_assets/images/javascript.jpg' style='"+style+"' id='fadeMe' />"; image.fadeUp(0); }, fadeUp : function(count) { var fadeImage = $("fadeMe"); count = count + 5; if (count < 100 ) { /*@cc_on /*@if (@_win32) fadeImage.style.filter ="alpha(opacity="+ count +")"; @else @*/ fadeImage.style.opacity= (count/100); /*@end @*/ var callback = function() { image.fadeUp(count); } setTimeout(callback,50); } } };
Add Element, Fade Up YUI var image = { insert : function(){ if (YAHOO.util.Dom.get("fadeMe")) { YAHOO.util.Dom.get("image").removeChild(YAHOO.util.Dom.get("fadeMe")); } var newImage = document.createElement("img"); newImage.src= "/web/samples/presentation/_assets/images/javascript.jpg"; newImage.setAttribute("id","fadeMe"); newImage.style.opacity=0; YAHOO.util.Dom.get("image").appendChild(newImage); image.fadeUp(0); }, fadeUp : function(count) { var fadeImage = YAHOO.util.Dom.get("fadeMe") count = count + 5; if (count < 100 ) { /*@cc_on /*@if (@_win32) fadeImage.style.filter ="alpha(opacity="+ count +")"; @else @*/ fadeImage.style.opacity= (count/100); /*@end @*/ var callback = function() { image.fadeUp(count); } setTimeout(callback,50); } } }
Pure JavaScript (anecdotal) • The Good: • Light. Fast. Standards based • The Bad: • More verbose. API awkward? • The Ugly: • Doesn’t work in 65% of the browsers worldwide
WIWND(anecdotal) • The Good: • Light. Fast. Handles “big” x-browser stuff. Fun (for me) • The Bad: • Not clever / less convenient. • The Ugly: • Lots of heavy lifting. Lots.
Dojo (anecdotal) • The Good: • Easy to pick up. HTML to include GZipped/CDN version right on download page • The Bad: • Slower. No JSON+Callback functionality. Need to learn to think in “Dojo” • The Ugly: • Documentation
jQuery (anecdotal) • The Good: • Easy to pick up. Fast, succinct code. Chaining is fun. Solid documentation. • The Bad: • No JSON+Callback functionality. Need to learn to think in “jQuery.” CDN link not promoted. • The Ugly:
Prototype/Scriptaculous (anecdotal) • The Good: • Feels more like JavaScript. Deep. • The Bad: • No JSON+Callback functionality. Promoted code is not minified. Slowest of the libraries. • The Ugly: • “Blototype.” Reading documentation was like being punched in the face.
YUI (anecdotal) • The Good: • Fast. Incredible documentation. CDN + single file functionality. Deep bench of advanced functionality. JSON+Callback functionality. • The Bad: • Limited, generic effects. Leaves more basic work than other libraries. • The Ugly: • Code.is.Awkward.To.Me()