the dom is a mess @ yahoo
DESCRIPTION
A talk that I gave at Yahoo, in January 2009, about the DOM.TRANSCRIPT
![Page 1: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/1.jpg)
The DOM is a MessJohn Resig
http://ejohn.org/ - http://twitter.com/jeresig/
![Page 2: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/2.jpg)
A Tour of the DOM✦ A messy DOM✦ Writing Cross-Browser Code✦ Common Features
✦ CSS Selector Engine✦ DOM Modification✦ Events
![Page 3: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/3.jpg)
Messy✦ Nearly every DOM method is broken in
some way, in some browser.✦ Some old:
✦ getElementById✦ getElementsByTagName
✦ Some new:✦ getElementsByClassName✦ querySelectorAll
![Page 4: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/4.jpg)
getElementById✦ Likely the most commonly used DOM
method✦ A couple weird bits:
✦ IE and older versions of Opera returning elements with a name == id
✦ Does not easily work in XML documents
![Page 5: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/5.jpg)
getElementsByTagName✦ Likely tied for most-commonly-used
DOM method✦ Riddled with bugs in IE:
✦ “*” returns no elements in IE 5.5✦ “*” returns no elements on <object>
elements in IE 7✦ .length gets overwritten in IE if an
element with an ID=”length” is found
![Page 6: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/6.jpg)
getElementsByClassName✦ Landed in Firefox 3, Safari 3, Opera 9.6✦ A few knotty issues:
✦ HTMLElement.prototype .getElementsByClassNamecouldn’t be overwritten in Firefox
✦ Opera doesn’t match a second-specified class (e.g. class=”a b”, b isn’t found)
![Page 7: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/7.jpg)
querySelectorAll✦ Find DOM elements using CSS selectors✦ In Firefox 3.1, Safari 3.1, Opera 10, IE 8✦ Birthing pains:
✦ Doesn’t exist in quirks mode, in IE 8✦ Safari 3.1 had memory out of bounds
problems✦ Safari 3.2 can’t match uppercase
characters in quirks mode✦ #id doesn’t match in XML documents
![Page 8: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/8.jpg)
Moral✦ If there’s a DOM method, there’s probably
a problem with it somewhere, in some capacity.
![Page 9: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/9.jpg)
Cross-Browser Code
![Page 10: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/10.jpg)
Strategies✦ Pick your browsers✦ Know your enemies✦ Write your code
![Page 11: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/11.jpg)
Cost / Benefit
IE 7 IE 6 FF 3 Safari 3 Opera 9.5
Cost Benefit
Draw a line in the sand.
![Page 12: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/12.jpg)
Graded Support
Yahoo Browser Compatibility
![Page 13: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/13.jpg)
Browser Support GridIE Firefox Safari Opera Chrome
Previous 6.0 2.0 3.0 9.5
Current 7.0 3.0 3.2 9.6 Current
Next 8.0 3.1 4.0 10.0
jQuery Browser Support
![Page 14: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/14.jpg)
Browser Support GridIE Firefox Safari Opera Chrome
Previous 6.0 2.0 3.0 9.5
Current 7.0 3.0 3.2 9.6 Current
Next 8.0 3.1 4.0 10.0
jQuery 1.3 Browser Support
![Page 15: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/15.jpg)
Know Your Enemies
JavaScript CodeMissing Features
Regressions
Browser Bugs
ExternalCode, Markup
Bug Fixes
Points of Concern for JavaScript Code
![Page 16: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/16.jpg)
Know Your Enemies
JavaScript CodeMissing Features
Regressions
Browser Bugs
ExternalCode, Markup
Bug Fixes
Points of Concern for JavaScript Code
![Page 17: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/17.jpg)
Browser Bugs✦ Generally your primary concern✦ Your defense is a good test suite
✦ Prevent library regressions✦ Analyze upcoming browser releases
✦ Your offense is feature simulation✦ What is a bug?
✦ Is unspecified, undocumented, behavior capable of being buggy?
![Page 18: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/18.jpg)
Test, Test, Test
1446 Tests, 9 browsers
![Page 19: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/19.jpg)
Know Your Enemies
JavaScript CodeMissing Features
Regressions
Browser Bugs
ExternalCode, Markup
Bug Fixes
Points of Concern for JavaScript Code
![Page 20: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/20.jpg)
External Code✦ Making your code resistant to any
environment✦ Found through trial and error✦ Integrate into your test suite
✦ Other libraries✦ Strange code uses
![Page 21: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/21.jpg)
Environment Testing✦ 100% Passing:
✦ Standards Mode✦ Quirks Mode✦ Inline with Prototype + Scriptaculous✦ Inline with MooTools
✦ Work in Progress:✦ XHTML w/ correct mimetype✦ With Object.prototype✦ In XUL (Firefox Extensions)✦ In Rhino (with Env.js)
![Page 22: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/22.jpg)
Object.prototype Object.prototype.otherKey = "otherValue"; var obj = { key: "value" }; for ( var prop in object ) { if ( object.hasOwnProperty( prop ) ) { assert( prop, "key", "There should only be one iterated property." ); } }
![Page 23: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/23.jpg)
Greedy IDs <form id="form"> <input type="text" id="length"/> <input type="submit" id="submit"/> </form>
document.getElementsByTagName("input").length
![Page 24: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/24.jpg)
Order of Stylesheets✦ Putting stylesheets before code guarantees
that they’ll load before the code runs.✦ Putting them after can create an
indeterminate situation.
![Page 25: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/25.jpg)
Pollution✦ Make sure your code doesn’t break
outside code✦ Use strict code namespacing✦ Don’t extend outside objects, elements
✦ Bad:✦ Introducing global variables✦ Extending native objects (Array, Object)✦ Extending DOM natives
![Page 26: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/26.jpg)
Pollution
http://mankz.com/code/GlobalCheck.htm
![Page 27: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/27.jpg)
Know Your Enemies
JavaScript CodeMissing Features
Regressions
Browser Bugs
ExternalCode, Markup
Bug Fixes
Points of Concern for JavaScript Code
![Page 28: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/28.jpg)
Missing Features✦ Typically older browsers missing specific
features✦ Optimal solution is to gracefully
degrade✦ Fall back to a simplified page
✦ Can’t make assumptions about browsers that you can’t support✦ If it’s impossible to test them, you must
provide a graceful fallback✦ Object detection works well here.
![Page 29: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/29.jpg)
Object Detection✦ Check to see if an object or property
exists✦ Useful for detecting an APIs existence✦ Doesn’t test the compatibility of an API
✦ Bugs can still exist - need to test those separately with feature simulation
![Page 30: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/30.jpg)
Event Binding function attachEvent( elem, type, handle ) { // bind event using proper DOM means if ( elem.addEventListener ) elem.addEventListener(type, handle, false); // use the Internet Explorer API else if ( elem.attachEvent ) elem.attachEvent("on" + type, handle); }
![Page 31: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/31.jpg)
Fallback Detection if ( typeof document !== "undefined" && (document.addEventListener || document.attachEvent) && document.getElementsByTagName && document.getElementById ) { // We have enough of an API to // work with to build our application } else { // Provide Fallback }
![Page 32: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/32.jpg)
Fallback✦ Figure out a way to reduce the
experience✦ Opt to not execute any JavaScript
✦ Guarantee no partial API✦ (e.g. DOM traversal, but no Events)
✦ Redirect to another page, or just work unobtrusively
✦ Working on a ready() fallback for jQuery
![Page 33: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/33.jpg)
Know Your Enemies
JavaScript CodeMissing Features
Regressions
Browser Bugs
ExternalCode, Markup
Bug Fixes
Points of Concern for JavaScript Code
![Page 34: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/34.jpg)
Bug Fixes✦ Don’t make assumptions about browser
bugs.✦ Assuming that a browser will always
have a bug is foolhardy✦ You will become susceptible to fixes✦ Browsers will become less inclined to fix
bugs✦ Look to standards to make decisions about
what are bugs
![Page 35: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/35.jpg)
Failed Bug Fix in FF 3 // Shouldn't work var node = documentA.createElement("div"); documentB.documentElement.appendChild( node ); // Proper way var node = documentA.createElement("div"); documentB.adoptNode( node ); documentB.documentElement.appendChild( node );
![Page 36: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/36.jpg)
Feature Simulation✦ More advanced than object detection✦ Make sure an API works as advertised✦ Able to capture bug fixes gracefully
![Page 37: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/37.jpg)
Verify API // Run once, at the beginning of the program var ELEMENTS_ONLY = (function(){ var div = document.createElement("div"); div.appendChild( document.createComment("test" ) ); return div.getElementsByTagName("*").length === 0; })(); // Later on: var all = document.getElementsByTagName("*"); if ( ELEMENTS_ONLY ) { for ( var i = 0; i < all.length; i++ ) { action( all[i] ); } } else { for ( var i = 0; i < all.length; i++ ) { if ( all[i].nodeType === 1 ) { action( all[i] ); } } }
![Page 38: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/38.jpg)
Figure Out Naming <div id="test" style="color:red;"></div> <div id="test2"></div> <script> // Perform the initial attribute check var STYLE_NAME = (function(){ var div = document.createElement("div"); div.style.color = "red"; if ( div.getAttribute("style") ) return "style"; if ( div.getAttribute("cssText") ) return "cssText"; })(); // Later on: window.onload = function(){ document.getElementsById("test2").setAttribute( STYLE_NAME, document.getElementById("test").getAttribute( STYLE_NAME ) ); }; </script>
![Page 39: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/39.jpg)
Know Your Enemies
JavaScript CodeMissing Features
Regressions
Browser Bugs
ExternalCode, Markup
Bug Fixes
Points of Concern for JavaScript Code
![Page 40: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/40.jpg)
Regressions✦ Removing or changing unspecified APIs✦ Object detection helps here✦ Monitor upcoming browser releases
✦ All vendors provide access to beta releases
✦ Diligence!✦ Example: IE 7 introduced
XMLHttpRequest with file:// bug✦ Test Suite Integration
![Page 41: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/41.jpg)
Object Failover function attachEvent( elem, type, handle ) { // bind event using proper DOM means if ( elem.addEventListener ) elem.addEventListener(type, handle, false); // use the Internet Explorer API else if ( elem.attachEvent ) elem.attachEvent("on" + type, handle); }
![Page 42: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/42.jpg)
Safe Cross-Browser Fixes✦ The easiest form of fix✦ Unifies an API across browsers✦ Implementation is painless
![Page 43: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/43.jpg)
Unify Dimensions // ignore negative width and height values if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) value = undefined;
![Page 44: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/44.jpg)
Prevent Breakage if ( name == "type" && elem.nodeName.toLowerCase() == "input" && elem.parentNode ) throw "type attribute can't be changed";
![Page 45: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/45.jpg)
Untestable Problems✦ Has an event handler been bound?✦ Will an event fire?✦ Do CSS properties like color or opacity
actually affect the display?✦ Problems that cause a browser crash.✦ Problems that cause an incongruous API.
![Page 46: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/46.jpg)
Impractical to Test✦ Performance-related issues✦ Determining if Ajax requests will work
![Page 47: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/47.jpg)
Battle of Assumptions✦ Cross-browser development is all about
reducing the number of assumptions✦ No assumptions indicates perfect code
✦ Unfortunately that’s an unobtainable goal
✦ Prohibitively expensive to write✦ Have to draw a line at some point
![Page 48: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/48.jpg)
DOM Traversal✦ Many methods of DOM traversal✦ One unanimous solution:
✦ CSS Selector Engine
![Page 49: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/49.jpg)
Traditional DOM✦ getElementsByTagName✦ getElementById✦ getElementsByClassName
✦ in FF3, Safari 3, Opera 9.6✦ .children
✦ only returns elements (in all, and FF 3.1)✦ getElementsByName✦ .all[id]
✦ Match multiple elements by ID
![Page 50: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/50.jpg)
Top-Down CSS Selector✦ Traditional style of traversal
✦ Used by all major libraries✦ Work from left-to-right✦ “div p”
✦ Find all divs, find paragraphs inside✦ Requires a lot of result merging✦ And removal of duplicates
![Page 51: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/51.jpg)
function find(selector, root){ root = root || document;
var parts = selector.split(" "), query = parts[0], rest = parts.slice(1).join(" "), elems = root.getElementsByTagName( query ), results = [];
for ( var i = 0; i < elems.length; i++ ) { if ( rest ) { results = results.concat( find(rest, elems[i]) ); } else { results.push( elems[i] ); } }
return results; }
![Page 52: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/52.jpg)
(function(){ var run = 0;
this.unique = function( array ) { var ret = [];
run++;
for ( var i = 0, length = array.length; i < length; i++ ) { var elem = array[ i ];
if ( elem.uniqueID !== run ) { elem.uniqueID = run; ret.push( array[ i ] ); } }
return ret; }; })();
![Page 53: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/53.jpg)
Bottom-Up✦ Work from right-to-left
✦ (How CSS Engines work in browsers.)✦ “div p”
✦ Find all paragraphs, see if they have a div ancestor, etc.
✦ Fast for specific queries✦ “div #foo”
✦ Deep queries get slow (in comparison)✦ “#foo p”
![Page 54: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/54.jpg)
Bottom-Up✦ Some nice features:
✦ Only one DOM query✦ No merge/unique required (except for “div, span”)
✦ Everything is a process of filtering
![Page 55: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/55.jpg)
function find(selector, root){ root = root || document;
var parts = selector.split(" "), query = parts[parts.length - 1], rest = parts.slice(0,-1).join("").toUpperCase(), elems = root.getElementsByTagName( query ), results = [];
for ( var i = 0; i < elems.length; i++ ) { if ( rest ) { var parent = elems[i].parentNode; while ( parent && parent.nodeName != rest ) { parent = parent.parentNode; }
if ( parent ) { results.push( elems[i] ); } } else { results.push( elems[i] ); } }
return results; }
![Page 56: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/56.jpg)
CSS to XPath✦ Browsers provide XPath functionality✦ Collect elements from a document✦ Works in all browsers
✦ In IE it only works on HTML documents
✦ Fast for a number of selectors (.class, “div div div”)✦ Slow for some others: #id
✦ Currently used by Dojo and Prototype
![Page 57: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/57.jpg)
if ( typeof document.evaluate === "function" ) { function getElementsByXPath(expression, parentElement) { var results = []; var query = document.evaluate(expression, parentElement || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0, length = query.snapshotLength; i < length; i++) results.push(query.snapshotItem(i)); return results; } }
![Page 58: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/58.jpg)
Goal CSS 3 XPath
All Elements * //*
All P Elements p //p
All Child Elements p > * //p/*
Element By ID #foo //*[@id='foo']
Element By Class .foo //*[contains(concat(" ", @class, " ")," foo ")]
Element With Attribute *[title] //*[@title]
First Child of All P p > *:first-child //p/*[0]
All P with an A descendant Not possible //p[a]
Next Element p + * //p/following-sibling::*[0]
![Page 59: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/59.jpg)
querySelectorAll✦ The Selectors API spec from the W3C✦ Two methods:
✦ querySelector (first element)✦ querySelectorAll (all elements)
✦ Works on:✦ document✦ elements✦ DocumentFragments
✦ Implemented in:✦ Firefox 3.1, Safari 3, Opera 10, IE 8
![Page 60: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/60.jpg)
<div id="test"> <b>Hello</b>, I'm a ninja! </div> <div id="test2"></div> <script> window.onload = function(){ var divs = document.querySelectorAll("body > div"); assert( divs.length === 2, "Two divs found using a CSS selector." );
var b = document.getElementById("test").querySelector("b:only-child"); assert( b, "The bold element was found relative to another element." ); }; </script>
![Page 61: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/61.jpg)
<div id="test"> <b>Hello</b>, I'm a ninja! </div> <script> window.onload = function(){ var b = document.getElementById("test").querySelector("div b"); assert( b, "Only the last part of the selector matters." ); }; </script>
![Page 62: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/62.jpg)
DOM Modification✦ Injecting HTML✦ Removing Elements
![Page 63: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/63.jpg)
Injecting HTML✦ HTML 5:
insertAdjacentHTML✦ Already in IE, dicey support, at best✦ What can we use instead?
✦ We must generate our own HTML injection
✦ Use innerHTML to generate a DOM
![Page 64: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/64.jpg)
function getNodes(htmlString){ var map = { "<td": [3, "<table><tbody><tr>", "</tr></tbody></table>"], "<option": [1, "<select multiple='multiple'>", "</select>"] // a full list of all element fixes };
var name = htmlString.match(/<\w+/), node = name ? map[ name[0] ] || [0, "", ""];
var div = document.createElement("div"); div.innerHTML = node[1] + htmlString + node[2];
while ( node[0]-- ) div = div.lastChild;
return div.childNodes; }
assert( getNodes("<td>test</td><td>test2</td>").length === 2, "Get two nodes back from the method." ); assert( getNodes("<td>test</td>").nodeName === "TD", "Verify that we're getting the right node." );
![Page 65: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/65.jpg)
Element Mappings✦ option and optgroup need to be contained in a
<select multiple="multiple">...</select>✦ legend need to be contained in a
<fieldset>...</fieldset>✦ thead, tbody, tfoot, colgroup, and caption need to be
contained in a <table>...</table>✦ tr need to be in a
<table><thead>...</thead></table>, <table><tbody>...</tbody></table>, or a <table><tfoot>...</tfoot></table>
✦ td and th need to be in a<table><tbody><tr>...</tr></tbody></table>
✦ col in a<table><tbody></tbody><colgroup>...</colgroup></table>
✦ link and script need to be in adiv<div>...</div>
![Page 66: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/66.jpg)
DocumentFragment✦ Fragments can collect nodes✦ Can be appended or cloned in bulk✦ Super-fast (2-3x faster than normal)
![Page 67: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/67.jpg)
function insert(elems, args, callback){ if ( elems.length ) { var doc = elems[0].ownerDocument || elems[0], fragment = doc.createDocumentFragment(), scripts = getNodes( args, doc, fragment ), first = fragment.firstChild;
if ( first ) { for ( var i = 0; elems[i]; i++ ) { callback.call( root(elems[i], first), i > 0 ? fragment.cloneNode(true) : fragment ); } } } }
var divs = document.getElementsByTagName("div");
insert(divs, ["Name:"], function(fragment){ this.appendChild( fragment ); });
insert(divs, ["First Last"], function(fragment){ this.parentNode.insertBefore( fragment, this ); });
![Page 68: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/68.jpg)
Inline Script Execution✦ .append(“<script>var foo = 5;</script>”);✦ Must execute scripts globally✦ window.execScript() (for IE)✦ eval.call( window, “var foo = 5;” );✦ Cross-browser way is to build a script
element then inject it✦ Executes globally
![Page 69: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/69.jpg)
function globalEval( data ) { data = data.replace(/^\s+|\s+$/g, "");
if ( data ) { var head = document.getElementsByTagName("head")[0] || document.documentElement, script = document.createElement("script");
script.type = "text/javascript"; script.text = data;
head.insertBefore( script, head.firstChild ); head.removeChild( script ); } }
![Page 70: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/70.jpg)
Removing Elements✦ Have to clean up bound events
✦ IE memory leaks✦ Easy to do if it’s managed.
![Page 71: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/71.jpg)
Events✦ Three big problems with Events:
✦ Memory Leaks (in IE)✦ Maintaining ‘this’ (in IE)✦ Fixing event object inconsistencies
![Page 72: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/72.jpg)
Leaks✦ Internet Explorer 6 leaks horribly
✦ Other IEs still leak, not so badly✦ Attaching functions (that have a closure to
another node) as properties✦ Makes a leak:
elem.test = function(){ anotherElem.className = “foo”;};
![Page 73: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/73.jpg)
‘this’✦ Users like having their ‘this’ refer to the
target element✦ Not the case in IE✦ What’s the solution?
![Page 74: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/74.jpg)
Single Handler✦ Bind a single handler to an event✦ Call each bound function individually✦ Can fix ‘this’ and event object✦ How do we store the bound functions in a
way that won’t leak?
![Page 75: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/75.jpg)
Central Data Store✦ Store all bound event handlers in a central
object✦ Link elements to handlers✦ Keep good separation✦ One data store per library instance✦ Easy to manipulate later
✦ Trigger individual handlers✦ Easy to remove again, later
![Page 76: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/76.jpg)
Central Data StoreElement
Element
Element
Element
Element
#43
#67
#22
Data
Data
Events
Events
function click(){}function mouseover(){}
function click(){}
function click(){}
Data Store
![Page 77: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/77.jpg)
Multiple StoresElement
Element
Element
Element
Element
#43
#67
#22
Library A
Library B
#37
![Page 78: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/78.jpg)
Unique Element ID✦ The structure must hook to an element✦ Elements don’t have unique IDs✦ Must generate them and manage them✦ jQuery.data( elem, “events” );✦ Unique attribute name:
✦ elem.jQuery123456789 = 45;✦ Prevents collisions with other libraries
✦ We can store all sorts of data in here
![Page 79: The DOM is a Mess @ Yahoo](https://reader034.vdocuments.site/reader034/viewer/2022051512/540e2e698d7f72767e8b4c59/html5/thumbnails/79.jpg)
Questions?✦ http://ejohn.org/✦ http://twitter.com/jeresig/