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
// 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));
}
});
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;
}
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
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 );
};
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?
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
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”) == “”;
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