• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Secrets of JavaScript Libraries
 

Secrets of JavaScript Libraries

on

  • 44,336 views

This is the presentation from the "Secrets of JavaScript Libraries" panel at SXSW 2008.

This is the presentation from the "Secrets of JavaScript Libraries" panel at SXSW 2008.

Statistics

Views

Total Views
44,336
Views on SlideShare
30,893
Embed Views
13,443

Actions

Likes
61
Downloads
1,387
Comments
3

100 Embeds 13,443

http://ejohn.org 4390
http://mir.aculo.us 4282
http://ajaxian.com 2388
http://www.ajaxian.com 683
http://www.julien-verkest.fr 620
http://davidwalsh.name 467
http://www.jroller.com 89
http://www.dmxzone.com 73
http://www.xelaz.de 57
http://www.slideshare.net 40
http://www.ilovejs.net 36
http://kaloyan.info 28
http://extjs.com 25
http://feeds.feedburner.com 21
https://vif.gym.seminar-karlsruhe.de 17
http://static.slideshare.net 15
http://www.dnzone.com 15
http://www.ditii.com 14
http://themechanism.com 10
http://www.hanrss.com 10
http://www.kaloyan.info 8
file:// 7
http://webserver:82 7
http://demo.lippeblogs.de 7
http://wicucu.com 7
http://practicals-javascript.blogspot.com 5
http://www.fwzone.net 5
http://vif.gym.seminar-karlsruhe.de 5
http://www.ajaxman.net 4
http://all-for-women.com 4
http://tariqtechno.blogspot.com 3
http://phildawson.co.uk 3
http://phildawson.tumblr.com 3
http://mir.aculo.us. 3
http://www.flzone.com 3
http://ramonroche.com 3
http://lanyrd.com 3
http://dmxzone.com 3
http://translate.googleusercontent.com 3
http://swik.net 3
http://s.deeeki.com 2
http://hi.chibaole.com 2
http://superahlun.blogspot.com 2
http://nanotechplastics.com 2
http://web.archive.org 2
http://www.brijj.com 2
http://www.cars-and-motorcycles-and-trucks.com 2
http://www.filescon.com 2
http://66.102.9.104 2
http://localhost 2
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

13 of 3 previous next Post a comment

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

    Secrets of JavaScript Libraries Secrets of JavaScript Libraries Presentation Transcript

    • Secrets of JavaScript Libraries (Left to Right) Sam Stephenson (Prototype) Alex Russell (Dojo) Thomas Fuchs (Script.aculo.us) Andrew Dupont (Prototype) John Resig (jQuery)
    • What to Cover ✦ Topics: ✦ JavaScript Language ✦ Cross-Browser Code ✦ Events ✦ DOM Traversal ✦ Style ✦ Animations ✦ Distribution ✦ HTML Insertion
    • Secrets of the JavaScript Language
    • // Set up a class and create an element var Clock = Class.create({ initialize: function() { this.createElement(); }, createElement: function() { this.element = new Element(quot;divquot;); } });
    • // Display the time var Clock = Class.create({ initialize: function() { this.createElement(); }, createElement: function() { this.element = new Element(quot;divquot;); var date = new Date(); this.element.update( date.getHours() + quot;:quot; + date.getMinutes().toPaddedString(2) + quot;.quot; + date.getSeconds().toPaddedString(2) ); } }); $(document.body).insert(new Clock().element);
    • // Add the timer var Clock = Class.create({ initialize: function() { this.createElement(); this.createTimer(); }, createElement: function() { this.element = new Element(quot;divquot;); }, updateElement: function() { var date = new Date(); this.element.update( date.getHours() + quot;:quot; + date.getMinutes().toPaddedString(2) + quot;.quot; + date.getSeconds().toPaddedString(2) ); }, createTimer: function() { window.setInterval(500, this.updateElement.bind(this)); } });
    • // Add some options var Clock = Class.create({ color: quot;blackquot;, format: quot;#{hour}:#{minute}.#{second}quot;, initialize: function(options) { Object.extend(this, options); this.createElement(); this.createTimer(); }, createElement: function() { this.element = new Element(quot;divquot;); this.element.setStyle({ color: Clock().element); $(document.body).insert(new this.color }); }, $(document.body).insert(new Clock({ color: quot;redquot; }).element); $(document.body).insert(new Clock({ format: quot;#{hour}:#{minute}quot; }).element); updateElement: function() { this.element.update(this.format.interpolate(this.getTime())); }, getTime: function() { var date = new Date(); return { hour: date.getHours(), minute: date.getMinutes().toPaddedString(2), second: date.getSeconds().toPaddedString(2) } }, ...
    • // Use #toElement var Clock = Class.create({ ... toElement: function() { return this.element; } }); $(document.body).insert(new Clock()); $(document.body).down(quot;div.clock > divquot;).replace(new Clock()); $(document.body).down(quot;div.clockquot;).update(new Clock());
    • // Subclass it var AmPmClock = Class.create(Clock, { format: quot;#{hour}:#{minute}:#{second} #{ampm}quot;, getTime: function($super) { var time = $super(); time.ampm = time.hour < 12 ? quot;amquot; : quot;pmquot;; if (time.hour == 0) { time.hour = 12; } else if (time.hour > 12) { time.hour -= 12; } return time; } }); $(document.body).insert(new AmPmClock());
    • // Or monkeypatch it Object.extend(Clock.prototype, { format: quot;#{hour}:#{minute}:#{second} #{ampm}quot;, getTime: Clock.prototype.getTime.wrap(function(original) { var time = original(); time.ampm = time.hour < 12 ? quot;amquot; : quot;pmquot;; if (time.hour == 0) { time.hour = 12; } else if (time.hour > 12) { time.hour -= 12; } return time; } }); $(document.body).insert(new Clock());
    • Secrets of Cross-Browser Code
    • Browser Sniffing (wait, hear me out)
    • Conditionally evil
    • In order of desirability:
    • capabilities & quirks
    • Capabilities are easy to sniff
    • Quirks are... more troublesome
    • Object detection (for capabilities) if (document.evaluate) { // ... }
    • Distill to a boolean (for stuff in the gray area) var thinksCommentsAreElements = false; if ( document.createElement('!') ) { thinksCommentsAreElements = true; }
    • ...then sniff (for outright bugs/quirks) if (Prototype.Browser.IE) { element.style.filter = quot;alpha(opacity=50);quot;; }
    • Try to do the right thing, but don’t stand on principle
    • The social contract Good faith from browser makers ➝ good faith from web authors
    • Secrets of Quality Assurance
    • 1,500 750 0 1.5.0 1.5.1 1.6.0.2
    • Debugging ✦ Localize & Reproduce ✦ Find the smallest possible code that generates the problem ✦ Easy test-case generation ✦ ./gen.sh 1245 ajax ./gen.sh 1246 dom ✦ Simple logging, all browsers: document.getElementById(“output”) .innerHTML += “<br>” + msg;
    • Secrets of Events
    • Event handlers are tricky
    • Don’t store them on the element itself circular references = sadness
    • Build a global hashtable (like jQuery does it)
    • Element Data Store ✦ Each element gets a unique ID (bound w/ a unique property) elem.jQuery12345 = 1; ✦ Points back to large data structure: data[1] = { ... all element data here ... }; ✦ Data (like event handlers) are stored here data[1] = { handlers: { click: [ function(){...} ], ... } };
    • Then clean up on page unload So that IE doesn’t keep them in memory in perpetuum
    • Fixing memory leaks
    • Internet Explorer 6 red-headed stepchild
    • Don’t “prove” your code has no leaks (view the results!)
    • Drip is awesome
    • Test page: Create a bunch of elements, assign each an event handler, then remove each one from the page
    • Demonstrating the Leak Notice the stair-step effect
    • Plugging the leak // In Prototype, will remove all event listeners from an element Event.stopObserving(someElement); Event.purgeObservers = function(element, includeParent) { Element.select(element, quot;*quot;).each(Event.stopObserving); if ( includeParent ) Event.stopObserving( element ); };
    • Redefining functions add “before advice” to functions that need to remove elements
    • Code sample Element.Methods.update = Element.Methods.update.wrap( function(proceed, element, contents) { Event.purgeObservers(element); return proceed(element, contents); } ); Element.Methods.replace = Element.Methods.replace.wrap( function(proceed, element, contents) { Event.purgeObservers(element, true); return proceed(element, contents); } ); Element.Methods.remove = Element.Methods.remove.wrap( function(proceed, element) { Event.purgeObservers(element, true); return proceed(element); } ); Element.addMethods();
    • Drop-in fix for Prototype 1.6
    • Custom Events • Everything is event based if you squint • DOM is a good foundation • Terrible for stitching together non-DOM components and code • Composition == good, inheritance == bad • Custom events let us join loosely • When to use them? Pitfalls?
    • Custom Events (contd.) // in Dojo: dojo.subscribe(“/foo”, function(e, arg){ ... }); dojo.publish(“/foo”, [{ data: “thinger”}, “second arg”]); // in Prototype: document.observe(“event:foo”, function(e){ ... }); $(“nodeId”).fire(“event:foo”, { data: “thinger” }); // in jQuery: $(document).bind(“foo”, function(e, data, arg){ ... }); $(document).trigger(“foo”, [{ data: “thinger”}, “second”]);
    • Secrets of DOM Traversal
    • Selector Internals • Optimized DOM • Top-down vs. bottom-up • Caching + winnowing • XPath • Native, aka: querySelectorAll()
    • Selector Internals • Tradeoffs: size vs. speed vs. complexity • Prototype: XPath when possible, else DOM • Good perf, lower complexity, hackable • Dojo: all 3 methods, picks best available • Best perf, biggest, highest complexity • JQuery: DOM • Good perf, small size, extensiblity vs. forward-compat tradeoff
    • Secrets of Style
    • Computed Style ✦ IE way vs. Everyone else ✦ IE returns “actual value” ✦ Everyone else returns “pixel value” ✦ font-size: 2em; IE: “2em” Other: 24 ✦ Need to convert to common base ✦ Performance: Very costly, generally avoided wherever possible
    • Pixel Values in IE ✦ if ( !/^d+(px)?$/i.test( ret ) && /^d/.test( ret ) ) { // Remember the original values var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left; // Put in the new values to get a computed value out elem.runtimeStyle.left = elem.currentStyle.left; elem.style.left = ret || 0; ret = elem.style.pixelLeft + “px”; // Revert the changed values elem.style.left = style; elem.runtimeStyle.left = runtimeStyle; } ✦ From Dean Edwards: http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
    • Computed Style ✦ Safari 2 & 3: Giant mess for display: none elements ✦ Safari 2 ✦ getComputedStyle() returns undefined ✦ Safari 3 ✦ Always return empty strings for value ✦ Much harder to detect var ret = document.defaultView.getComputedStyle( elem, null ); return !ret || ret.getPropertyValue(”color”) == “”;
    • Finding dimensions
    • Dimensions of what? content box, border box, margin box...
    • DHTML properties clientWidth, offsetWidth
    • The value you want is not captured by any property Lorem ipsum dolor sit amet. width clientWidth offsetWidth
    • Computed styles getting padding & border value
    • The fool-proof, painful way Take the offsetWidth, then subtract computed padding & border
    • Code example Element.getCSSWidth = function(element) { element = $(element); return element.offsetWidth - parseFloat(element.getStyle(quot;borderLeftquot;)) - parseFloat(element.getStyle(quot;paddingLeftquot;)) - parseFloat(element.getStyle(quot;paddingRightquot;)) - parseFloat(element.getStyle(quot;borderRightquot;)); };
    • Secrets of Animation
    • Old-School “Effects”
    • setInterval
    • Events-based
    • Secrets ofJavaScript Deployment
    • CONTENT EXPIRATION
    • Concatenation
    • GZIP 4-5x smaller
    • Packaging • Dev vs. deployment constraints • No library a single file, but all ship that way • # of requests largest constraint • Sync vs. async • Static resource servers + CDNs • Dependency management matters! • Runtime vs. deployment
    • Packaging // in Dojo: dojo.provide(“foo.bar.Baz”); dojo.require(“dojox.dtl”); // in GWT: package com.foo.bar; import com.foo.bar.Blah; // in JSAN: JSAN.use(“foo.bar.Blah”); // exports handled by build tools
    • Packaging • The build-process divide • Library support vs. server concat/shrink • Can we strip “dead” code? • Social artifacts of packaging systems
    • HTML Insertion ✦ $(“div”).append(“<b>foo</b>”); ✦ Convert HTML String ✦ innerHTML ✦ Range: .createContextualFragment() ✦ Must purify first: ✦ Fix <table>s for IE (<tbody> wrap) ✦ Handle <option>s (contain in <select>)
    • HTML Insertion ✦ // Fix “XHTML ”-style tags in all browsers elem = elem.replace(/(<(w+)[^>]*?)/>/g, function(all, front, tag){ return tag.match(/^(abbr|br|col|img|input|link|meta|param| hr|area|embed)$/i) ? all : front + “></” + tag + “>”; }); ✦ $(“<abbr/>”).html(“hello!”).appendTo(“#foo”);
    • Script Execution ✦ Execute Script in Global Scope ✦ var head = document.getElementsByTagName(”head”)[0] || document.documentElement, script = document.createElement(”script”); script.type = “text/javascript”; if ( jQuery.browser.msie ) script.text = data; else script.appendChild( document.createTextNode( data ) ); head.appendChild( script ); head.removeChild( script );
    • Questions ✦ Panelists: ✦ John Resig (ejohn.org) ✦ Sam Stephenson (conio.net) ✦ Alex Russell (alex.dojotoolkit.org) ✦ Thomas Fuchs (script.aculo.us/thomas) ✦ Andrew Dupont (andrewdupont.net) ✦ Frameworks: ✦ Prototype (prototypejs.org) ✦ jQuery (jquery.com) ✦ Dojo (dojotoolkit.org) ✦ Script.aculo.us (script.aculo.us)