<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Web 3.0, 6 Bladed Razors, 7 Minute Abs</title>
	<atom:link href="http://www.zachleat.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zachleat.com/web</link>
	<description></description>
	<pubDate>Thu, 21 Aug 2008 06:02:08 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>Emulating onhashchange without setInterval</title>
		<link>http://www.zachleat.com/web/2008/08/21/onhashchange-without-setinterval/</link>
		<comments>http://www.zachleat.com/web/2008/08/21/onhashchange-without-setinterval/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 06:00:13 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[Back Button]]></category>

		<category><![CDATA[History]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=143</guid>
		<description><![CDATA[There is one limitation that all of the major JavaScript browser history management plugins have to hack around:  How to tell when there is a change to the location.hash?  Sure, you can tell when you&#8217;re modifying the hash yourself, but what if the user hits the back/forward button?
YUI&#8217;s History component and Really Simple [...]]]></description>
			<content:encoded><![CDATA[<p>There is one limitation that all of the major JavaScript browser history management plugins have to hack around:  How to tell when there is a change to the <code>location.hash</code>?  Sure, you can tell when you&#8217;re modifying the hash yourself, but what if the user hits the back/forward button?</p>
<p><a href="http://developer.yahoo.com/yui/history/">YUI&#8217;s History component</a> and Really Simple History both use setInterval with an internal variable to compare and find changes.  But this isn&#8217;t really an optimal solution.  As proper front end engineers, we should avoid timeouts as much as possible.  Internet Explorer 8 will have an <a href="http://msdn.microsoft.com/en-us/library/cc288209(VS.85).aspx">onhashchange event</a> that clients will be able to subscribe to.  That will be nice.  But surely, a cross browser solution without the use of setInterval exists.</p>
<p><strong>Look, a cross browser solution without the use of setInterval:</strong></p>
<ol>
<li>On initialization, we load an iframe onto the page that is positioned absolutely at -500px,-500px so the user can&#8217;t see it. It is a skeleton page that only needs cross browser code to add an &#8220;<code>onscroll</code>&#8221; event, and to be able to calculate the scrolled position of the iframe itself.  For my example, I use jQuery and the dimensions plugin to accomplish this, but it could easily be trimmed down to only the bare essentials (or ported to a different library).</li>
<li>To add an AJAX history entry into the browser&#8217;s history under an assigned hash string, we first add a <code>&lt;a name="hashString"&gt;hashString&lt;/a&gt;</code> to the <code>&lt;body&gt;</code> tag of the iframe.  Using css to increase the size of the a tag proportional to the iframe&#8217;s height, we can guarantee scrolling will happen.</li>
<li>Then, we change the <code>location.hash</code> of the iframe to point to that <code>&lt;a&gt;</code> tag.  This will scroll the iframe to the content, and create a new entry in the browser&#8217;s <code>history</code> object.</li>
<li>Inside the iframe, we have our <code>onscroll</code> event that fires when the scrolling in the previous step took place.  (Minor IE-related workaround: The browser&#8217;s <code>history</code> object is changed, but the hash property doesn&#8217;t when attempting to read it later.  Instead, we find the <code>&lt;a&gt;</code> that matches up with the scrollY/pageOffsetY property inside of the iframe, and retrieve the matching hash from the <code>&lt;a&gt;</code> tag.)</li>
</ol>
<p>The nice thing about this approach is that you don&#8217;t even need a history manager anymore.  This little iframe will do all of your dirty work for you.  And it will even maintain your history alongside any other iframe browsing on the page.</p>
<p><strong>Advantages:</strong></p>
<ul>
<li>Can serve as back button support and full AJAX history manager.</li>
<li>Page Weight: the test page and iframe HTML files together weigh in at 2.76 KB.  That includes the non-jQuery JavaScript needed to do everything.</li>
<li>Cross browser: Tested in FF3, IE7, IE6, Opera 9.5, and Safari 3.1.2***</li>
</ul>
<p><strong>Limitations:</strong></p>
<ul>
<li>No bookmarking support.  We aren&#8217;t changing the top hash, we&#8217;re changing the iframe hash, so these aren&#8217;t bookmarkable.</li>
<li>***Safari 3 had an intermittent glitch when adding the first AJAX history entry, but then worked fine afterward.</li>
</ul>
<p><strong>Sample Example:</strong></p>
<ul>
<li>
<a href="http://www.zachleat.com/Projects/history/">My Test Page</a></li>
<li><a href="http://www.zachleat.com/Projects/history/history.zip">Download the test page (2 HTML files, and jQuery 1.2.6 and dimensions)</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/08/21/onhashchange-without-setinterval/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Double Whammy: OpenID and Microformats</title>
		<link>http://www.zachleat.com/web/2008/05/23/double-whammy-openid-and-microformats/</link>
		<comments>http://www.zachleat.com/web/2008/05/23/double-whammy-openid-and-microformats/#comments</comments>
		<pubDate>Fri, 23 May 2008 06:13:01 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[Application Design]]></category>

		<category><![CDATA[Interface Design]]></category>

		<category><![CDATA[Flickr]]></category>

		<category><![CDATA[hCard]]></category>

		<category><![CDATA[microformat]]></category>

		<category><![CDATA[OpenID]]></category>

		<category><![CDATA[Technorati]]></category>

		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=141</guid>
		<description><![CDATA[<a href="http://www.ownyouridentity.com/2008/04/30/get-satisfactions-nice-import-profile-feature/">Own your Identity had a great post today</a> detailing a great feature on the signup form of the <a href="http://getsatisfaction.com/people/new">Get Satisfaction</a> site.

They rely on the fact that sites like Twitter and Flickr publish an <a href="http://microformats.org/wiki/hcard">hCard microformat</a> for all of their users publicly on their website.]]></description>
			<content:encoded><![CDATA[<h3>Microformategery</h3>
<p><a href="http://www.ownyouridentity.com/2008/04/30/get-satisfactions-nice-import-profile-feature/">Own your Identity had a great post today</a> detailing a great feature on the signup form of the <a href="http://getsatisfaction.com/people/new">Get Satisfaction</a> site.</p>
<p>They rely on the fact that sites like Twitter and Flickr publish an <a href="http://microformats.org/wiki/hcard">hCard microformat</a> for all of their users publicly on their website.  If you go to <a href="http://twitter.com/zachleat/">my twitter page</a> and view the source, you'll find the following code available to anyone (without authentication):</p>
<div class="syntax_hilite">
<div id="html-1">
<div class="html"><span style="color: #009900;"><a href="http://december.com/html/4/element/address.html"><span style="color: #000000; font-weight: bold;">&lt;address&gt;</span></a></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><a href="http://december.com/html/4/element/ul.html"><span style="color: #000000; font-weight: bold;">&lt;ul</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"about vcard entry-author"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"label"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Name<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span> <span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"fn"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Zach Leatherman<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"label"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Location<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span> <span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"adr"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Omaha, NE USA<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"label"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Web<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span> <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"http://www.zachleat.com/"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"url"</span> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">"me"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>http://www.zachle...<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"bio"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span><span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"label"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>Bio<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span> <span style="color: #009900;"><a href="http://december.com/html/4/element/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"bio"</span><span style="color: #000000; font-weight: bold;">&gt;</span></a></span>UI Programmer, JavaScript Enthusiast, Soccer Hooligan<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ul&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/address&gt;</span></span></div>
</div>
</div>
<p></p>
<p>The premise here is that hCard tells you how to parse this markup to get usable information.  The <code>adr</code> CSS class tells you what my address is.  The <code>fn</code> CSS class tells you what my name is, and so on.  So, Get Satisfaction goes and spiders this page behind the scenes and autopopulates your profile with what it can find.  Pretty sweet.</p>
<p>Now, they don't limit you to the services they provide, which are: Flickr, Technorati, Twitter, Upcoming, and last.fm.  They provide an Other category for any hCard enabled URL (your personal homepage or perhaps an <a href="http://microformats.org/wiki/hresume">hResume</a> you have posted on the web).</p>
<h3>Integrate with OpenID</h3>
<p>However, why not take it to the next level?  Why not integrate this microformat functionality WITH an openid login system?  You'd be able to kill two birds (not a twitter joke) with one stone in some cases, since both Twitter and Technorati are also OpenID producers (re-echo: We need more consumers).</p>
<p>So, not only do you get the benefits of having OpenID authentication on your website, but you'd be able to prepopulate a certain amount of profile data with an hCard parser.  And the best part is, if you already have a <a href="http://remysharp.com/2008/04/24/stop-using-openid-why-how/">nice clean user interface</a> set up to handle different OpenID producers, there wouldn't be any additional clutter on the interface to get this benefit.  It'd be transparent to the user when it works, and fall back to a normal empty profile form when it doesn't.</p>
<p>What I'd like to see, is more sites that are OpenID producers, also serve hCard microformats as well.  If we can get all the major producers on board, we'd have a nice tidy little system going.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/05/23/double-whammy-openid-and-microformats/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Selecting XML Nodes with JavaScript (Peril of getElementsByTagName)</title>
		<link>http://www.zachleat.com/web/2008/05/10/selecting-xml-with-javascript/</link>
		<comments>http://www.zachleat.com/web/2008/05/10/selecting-xml-with-javascript/#comments</comments>
		<pubDate>Sat, 10 May 2008 23:27:02 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[XML]]></category>

		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=132</guid>
		<description><![CDATA[Parsing XML in the browser can be a tricky beast.  There are many different wrong ways to do it, which can leave you cold and naked in a snowstorm if you're not careful.  So, let's put on the metaphorical electric one-sie of standards based code and let the power of Edison heat our JavaScript code like the innards of a <a href="http://starwars.wikia.com/wiki/Tauntaun">tauntaun</a>.]]></description>
			<content:encoded><![CDATA[<p><em>There are two popular camps for ajax data formats right now: XML and JSON.  Both have their (dis-)advantages.  The purpose of this article is  to show you how to effectively parse XML in the browser.</em></p>
<h3>Super Fast Beginner's Primer</h3>
<ul>
<li>Case 1: <strong>Node</strong> (or un-namespaced node, null-namespaced node): a node without a prefix, such as child here:<br />
<code>&lt;child/&gt;</code></li>
<li>Case 2: <strong>Default namespaced node</strong>: a node without a prefix, but a parent node (or itself) has a xmlns attribute, like both root and child here:<br />
<code>&lt;root xmlns="http://example.com/"&gt;&lt;child/&gt;&lt;/root&gt;</code></li>
<li>Case 3: <strong>Namespaced node</strong>: a node with a prefix, and a parent node (or itself) declaring a xmlns with that prefix attached, like both child and root here:<br />
<code>&lt;prefix:root prefix:xmlns="http://example.com/"&gt;&lt;prefix:child/&gt;&lt;/root&gt;</code></li>
</ul>
<h3>/End Primer</h3>
<p>Parsing XML in the browser can be a tricky beast.  There are many different wrong ways to do it, which can leave you cold and naked in a snowstorm if you're not careful.  So, let's put on the metaphorical electric one-sie of standards based code and let the power of Edison heat our JavaScript code like the innards of a <a href="http://starwars.wikia.com/wiki/Tauntaun">tauntaun</a>.</p>
<p>If there is one thing you can take away from this article, its that the problems with XML in JavaScript have already been solved, and there is library code out there to do the job for you.  But libraries aren't a substitute for knowledge (abstraction is a dangerous thing during education), so let's learn <strong>why</strong> these problems are occurring so we can wrinkle our gray matter and increase our productivity at the same time.</p>
<h2>Use Cases</h2>
<p>These are the main use cases that takes place when selecting a node inside of an XML document:</p>
<ol>
<li><strong>Case 1</strong>: Selecting un-namespaced nodes (or nodes in the null namespace):
<div class="syntax_hilite">
<div id="xml-2">
<div class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;root<span style="font-weight: bold; color: black;">&gt;</span></span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;child</span><span style="font-weight: bold; color: black;">/&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/root<span style="font-weight: bold; color: black;">&gt;</span></span></span></div>
</div>
</div>
<p></p>
<p>This one is easy.  If you can guarantee that your XML will never have any namespaces, you're home free.  Take your get out of jail free card and run for the hills.  Using this assumption, you can query nodes inside of your XML Document object using nothing other than <code>getElementsByTagName()</code>.  Lucky bastard.</p>
<div class="syntax_hilite">
<div id="javascript-3">
<div class="javascript"><span style="color: #009900; font-style: italic;">// assume oDocEl is the documentElement inside of an XML Document </span><br />
<span style="color: #003366; font-weight: bold;">var</span> correctForCase1 = oDocEl.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'child'</span><span style="color: #66cc66;">&#41;</span>;</div>
</div>
</div>
<p>
</li>
<li><strong>Case 2</strong>: Selecting default namespaced nodes:
<div class="syntax_hilite">
<div id="xml-4">
<div class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;root</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">"http://example.com/"</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;child</span><span style="font-weight: bold; color: black;">/&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/root<span style="font-weight: bold; color: black;">&gt;</span></span></span></div>
</div>
</div>
<p>
Tread lightly, this is about to get serious.  In most cases, historically I had thought that using the solution described for Case 1 would be sufficient in this case.  I had learned awhile back that Internet Explorer treats node names (including namespace prefix and local name together) as one string.  So, the method for Case 1 should work for Internet Explorer, especially in the case of node sans prefix.  In Firefox, you'd have to use getElementsByTagNS(), but that would be just a simple wrapper.</p>
<p>Then I met an Internet Explorer exception.  The only unique thing about this installation of Internet Explorer 7 was that it had MSXML 6 installed, when all the other computers I had tested on were using MSXML 3.  The obvious conclusion here is that MSXML 6 won't select child nodes for Case 2.</p>
<div class="syntax_hilite">
<div id="javascript-5">
<div class="javascript"><span style="color: #003366; font-weight: bold;">var</span> incorrectForCase2 = oDocEl.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'child'</span><span style="color: #66cc66;">&#41;</span>;</div>
</div>
</div>
<p>
Here's the right way to select nodes for Case 2.  Fair warning, to keep the code examples here simple, this solution requires Sarissa (sarissa.js and sarissa_ieemu_xpath.js) to be included on the page prior to usage.</p>
<div class="syntax_hilite">
<div id="javascript-6">
<div class="javascript"><span style="color: #009900; font-style: italic;">// assume oDoc is an XML Document object.</span><br />
oDoc.<span style="color: #006600;">setProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"SelectionNamespaces"</span>, <span style="color: #3366CC;">"xmlns:whatever='http://example.com/'"</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #003366; font-weight: bold;">var</span> oDocEl = oDoc.<span style="color: #006600;">documentElement</span>;<br />
<span style="color: #003366; font-weight: bold;">var</span> correctForCase2A = oDocEl.<span style="color: #006600;">selectNodes</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'whatever:child'</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #003366; font-weight: bold;">var</span> correctForCase2B = oDocEl.<span style="color: #006600;">selectSingleNode</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'whatever:child'</span><span style="color: #66cc66;">&#41;</span>;</div>
</div>
</div>
<p>
Note how we've mapped what was the default namespace (without a prefix) to be a namespace WITH a prefix during the node selection.</p>
<p>It should be noted that when the resultant XML has a namespace attached (Case 2 and 3), Firefox works fine using getElementsByTagNameNS.  IE doesn't include support for that method, however, so we're forced to find a more complete solution.
</li>
<li><strong>Case 3</strong>: Select a non-default namespaced node:
<div class="syntax_hilite">
<div id="xml-7">
<div class="xml"><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;root</span> prefix:<span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">"http://example.com/"</span><span style="font-weight: bold; color: black;">&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;prefix</span>:child<span style="font-weight: bold; color: black;">/&gt;</span></span><span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/root<span style="font-weight: bold; color: black;">&gt;</span></span></span></div>
</div>
</div>
<p>
As I mentioned in Case 2, normally (pre-MSXML 6), you'd be able to perform a <code>getElementsByTagName('prefix:child')</code> in IE and use getElementsByTagNameNS in Firefox as usual.  But that has changed now.  We need to set up the SelectionNamespaces property for IE, and we'll use Sarissa to take it cross-browser for us.</p>
<div class="syntax_hilite">
<div id="javascript-8">
<div class="javascript"><span style="color: #009900; font-style: italic;">// assume oDoc is an XML Document object.</span><br />
oDoc.<span style="color: #006600;">setProperty</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"SelectionNamespaces"</span>, <span style="color: #3366CC;">"xmlns:whatever='http://example.com/'"</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #003366; font-weight: bold;">var</span> oDocEl = oDoc.<span style="color: #006600;">documentElement</span>;<br />
<span style="color: #003366; font-weight: bold;">var</span> correctForCase3A = oDocEl.<span style="color: #006600;">selectNodes</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'whatever:child'</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #003366; font-weight: bold;">var</span> correctForCase3B = oDocEl.<span style="color: #006600;">selectSingleNode</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'whatever:child'</span><span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #009900; font-style: italic;">// Note, this is the same code as Case 2 (which is a good thing) </span></div>
</div>
</div>
<p>
Note that we did <em>not</em> have to use the same prefix that was defined by the result XML.  We can map it to whatever we want (literally).
</li>
</ol>
<h2>Why is this important?</h2>
<p>Because most libraries don't handle Case 2 and Case 3, which are important parts of XML.  Here's some code straight from YUI 2.5.1 (DataSource component):</p>
<div class="syntax_hilite">
<div id="javascript-9">
<div class="javascript"><span style="color: #009900; font-style: italic;">// Line 1394</span><br />
<span style="color: #003366; font-weight: bold;">var</span> xmlNode = result.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span>key<span style="color: #66cc66;">&#41;</span>;<br />
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #66cc66;">&#40;</span>xmlNode &amp;&amp; xmlNode.<span style="color: #000066; font-weight: bold;">item</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span> &amp;&amp; xmlNode.<span style="color: #000066; font-weight: bold;">item</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">firstChild</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; data = xmlNode.<span style="color: #000066; font-weight: bold;">item</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">firstChild</span>.<span style="color: #006600;">nodeValue</span>;<br />
<span style="color: #66cc66;">&#125;</span><br />
<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;data = <span style="color: #3366CC;">""</span>;<br />
<span style="color: #66cc66;">&#125;</span></div>
</div>
</div>
<p></p>
<p>Notice how they just do getElementsByTagName.  For shame :(  jQuery doesn't handle Case 2 or Case 3 either.  (Proof is an exercise to the reader :P)  So, if you have XML data sources with namespaces, it would do you well to use the solution presented in this article, or you're going to have headaches later.</p>
<h2>Springer's Final Word</h2>
<p>Don't use getElementsByTagName.  If you do, PLEASE include a note saying that your code isn't going to support namespaced XML.  Branch your selection code to check if Sarissa has been included on the page, and use Sarissa for namespaced XML if it's there.  It's not fun to be pidgin-holed into the simplest case of XML.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/JavaScript" rel="tag">JavaScript</a>, <a href="http://technorati.com/tag/XML" rel="tag"> XML</a>, <a href="http://technorati.com/tag/selectNodes" rel="tag"> selectNodes</a>, <a href="http://technorati.com/tag/YUI" rel="tag"> YUI</a>, <a href="http://technorati.com/tag/jQuery" rel="tag"> jQuery</a>, <a href="http://technorati.com/tag/getElementsByTagName" rel="tag"> getElementsByTagName</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/05/10/selecting-xml-with-javascript/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Javascript Objects are NOT JSON</title>
		<link>http://www.zachleat.com/web/2008/05/09/javascript-objects-are-not-json/</link>
		<comments>http://www.zachleat.com/web/2008/05/09/javascript-objects-are-not-json/#comments</comments>
		<pubDate>Sat, 10 May 2008 04:47:55 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=134</guid>
		<description><![CDATA[The headline should more accurately read "Javascript Objects are not necessarily JSON."  But that waters it down a bit, don't you think?
I know this has been posted a few times before, but this is not something I knew until recently, and after learning it, have noticed quite a few other people doing it wrong [...]]]></description>
			<content:encoded><![CDATA[<p><em>The headline should more accurately read "Javascript Objects are not <strong>necessarily</strong> JSON."  But that waters it down a bit, don't you think?</em></p>
<p>I know this has been posted a few times before, but this is not something I knew until recently, and after learning it, have noticed quite a few other people doing it wrong as well.  So, to risk adding another reverb to the echo chamber, I'll post a link to a <a href="http://www.thefutureoftheweb.com/blog/json-is-not-just-object-notation">good explanation</a> by Jesse Skinner on the specifics of the JSON specification.</p>
<p>The main point here is that <strong>all object keys and strings in JSON must have double quotes.</strong>  I encourage you to look through the <a href="http://json.org/">train track specification</a> to verify for yourself.</p>
<p>If you try to use Captain <a href="http://www.json.org/json2.js">Crockford's JSON Parser</a>, it won't parse your string with single quotes or (un/single)-quoted object keys.  His parser has a nice regex checker built-in (and a walker callback to let you parse date strings into Date() objects).  It's a good way to verify that external data, or a data source not under your control, is safe to eval and use in your own code.</p>
<p>Here are a few quick examples:</p>
<h2>Valid JSON</h2>
<div class="syntax_hilite">
<div id="javascript-12">
<div class="javascript"><span style="color: #66cc66;">&#123;</span><span style="color: #3366CC;">"myKey"</span>: <span style="color: #3366CC;">"myString"</span><span style="color: #66cc66;">&#125;</span></div>
</div>
</div>
<p></p>
<p>Don't use single quotes.  Don't use unquoted object keys.</p>
<h2>Invalid JSON</h2>
<div class="syntax_hilite">
<div id="javascript-13">
<div class="javascript"><span style="color: #66cc66;">&#123;</span>myKey: <span style="color: #3366CC;">"myString"</span><span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#123;</span><span style="color: #3366CC;">'myKey'</span>: <span style="color: #3366CC;">'myString'</span><span style="color: #66cc66;">&#125;</span></div>
</div>
</div>
<p></p>
<p>Credits to Jonathan Snook for the <a href="http://www.snook.ca/archives/javascript/json_is_a_subse/">initial write-up</a> and Crockford for formalizing JSON.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/05/09/javascript-objects-are-not-json/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Surnamespacing</title>
		<link>http://www.zachleat.com/web/2008/05/07/surnamespacing/</link>
		<comments>http://www.zachleat.com/web/2008/05/07/surnamespacing/#comments</comments>
		<pubDate>Thu, 08 May 2008 01:30:31 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[Humor]]></category>

		<category><![CDATA[Java]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=133</guid>
		<description><![CDATA[Everyone has a library.  Everyone has their own utility classes and functions they're using in their own personal and contracted projects.  And now that everyone has a blog too, they're all releasing their libraries as open source, using the commando underoo philosophy of wild, free, and unrestricted naming schemes for their code.  Not anymore.  Let's surnamespace.]]></description>
			<content:encoded><![CDATA[<p>Everyone has a library.  Everyone has their own utility classes and functions they're using in their own personal and contracted projects.  And now that everyone has a blog too, they're all releasing their libraries as open source, using the commando underoo philosophy of wild, free, and unrestricted naming schemes for their code.  Not anymore.  Let's surnamespace.</p>
<p>What does surnamespacing give me?</p>
<ul>
<li><strong>Accountability</strong>: Your code is directly linked to your family honor.  You'd be surprised how hard people work at test cases and increased code coverage when the respect of their lineage is at stake.</li>
<li><strong>Connect</strong> with your Extended Family: Connect with programmers sharing your namespace, your family is now your development team.</li>
<li><strong>Minimize Collisons</strong>: The ball and chain associated with an imposed naming scheme means that we won't have everyone using foo and bar to hold their code, unless you're the lucky son of a bitch that has inherited that top notch surnamespace real estate.</li>
<li><strong>Faster</strong> Initial Development Cycle: Sometimes naming your library is the hardest part.  Skip this step and just surnamespace it.</li>
<p>Jesus Christ, please show me some examples:</p>
<p><strong>JavaScript Surnamespacing</strong></p>
<div class="syntax_hilite">
<div id="javascript-14">
<div class="javascript"><span style="color: #003366; font-weight: bold;">var</span> Christ = <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; Jesus: <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; walkOn: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>obj<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; turn: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>from, to<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; respawn: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span>;<br />
<span style="color: #009900; font-style: italic;">// Sample Usage</span><br />
Christ.<span style="color: #006600;">Jesus</span>.<span style="color: #006600;">walkOn</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'water'</span><span style="color: #66cc66;">&#41;</span>;<br />
Christ.<span style="color: #006600;">Jesus</span>.<span style="color: #006600;">turn</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'water'</span>, <span style="color: #3366CC;">'wine'</span><span style="color: #66cc66;">&#41;</span>;<br />
Christ.<span style="color: #006600;">Jesus</span>.<span style="color: #006600;">respawn</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div>
</div>
</div>
<p></p>
<p><strong>Java Surnamespacing</strong></p>
<div class="syntax_hilite">
<div id="java-15">
<div class="java">package Christ;<br />
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> Jesus <span style="color: #66cc66;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> walkOn<span style="color: #66cc66;">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&amp;bntl=1"><span style="color: #aaaadd; font-weight: bold;">String</span></a> s<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> turn<span style="color: #66cc66;">&#40;</span><a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&amp;bntl=1"><span style="color: #aaaadd; font-weight: bold;">String</span></a> from, <a href="http://www.google.com/search?q=allinurl%3AString+java.sun.com&amp;bntl=1"><span style="color: #aaaadd; font-weight: bold;">String</span></a> to<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> respawn<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span><br />
<span style="color: #66cc66;">&#125;</span></div>
</div>
</div>
<p></p>
<p><strong>PHP 6 Surnamespacing (<a href="http://php.net/~derick/meeting-notes.html">projected usage</a>)</strong></p>
<div class="syntax_hilite">
<div id="php-16">
<div class="php">namespace Christ <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; <span style="color:#000000; font-weight:bold;">class</span> Jesus <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; public <span style="color:#000000; font-weight:bold;">function</span> walkOn<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$obj</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; public <span style="color:#000000; font-weight:bold;">function</span> turn<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF;">$from</span>, <span style="color:#0000FF;">$to</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; public <span style="color:#000000; font-weight:bold;">function</span> respawn<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
<span style="color:#006600; font-weight:bold;">&#125;</span></div>
</div>
</div>
<p></p>
<p><strong>Update</strong>: Apparently I can't write Java code.  Don't tell work.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/05/07/surnamespacing/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Don&#8217;t Let the Door Hit You Onunload and Onbeforeunload</title>
		<link>http://www.zachleat.com/web/2008/04/22/dont-let-the-door-hit-you-onunload-and-onbeforeunload/</link>
		<comments>http://www.zachleat.com/web/2008/04/22/dont-let-the-door-hit-you-onunload-and-onbeforeunload/#comments</comments>
		<pubDate>Wed, 23 Apr 2008 04:51:08 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[Interface Design]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Web Browsers]]></category>

		<category><![CDATA[Ajax]]></category>

		<category><![CDATA[Gmail]]></category>

		<category><![CDATA[Opera]]></category>

		<category><![CDATA[Undo]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=126</guid>
		<description><![CDATA[Many people attempt a last ditch effort to save page state in the browser by using the onunload or onbeforeunload events.  This has been studied at great length by Patrick Hunlock,  who uses the perhaps now common knowledge of using a Synchronous Ajax call to perform the page state save.
Another use for the [...]]]></description>
			<content:encoded><![CDATA[<p>Many people attempt a last ditch effort to save page state in the browser by using the onunload or onbeforeunload events.  This has been studied at great length by <a href="http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript">Patrick Hunlock</a>,  who uses the perhaps now common knowledge of using a Synchronous Ajax call to perform the page state save.</p>
<p>Another use for the onbeforeunload event to allow the user to cancel the action that initiated the user leaving in the first place.  Gmail uses this technique when the user is in the middle of writing a draft of an e-mail and attempts to leave the page.</p>
<p><a href='http://www.zachleat.com/web/wp-content/uploads/2008/04/gmail-confirm.png'><img src="http://www.zachleat.com/web/wp-content/uploads/2008/04/gmail-confirm.png" alt="" title="gmail-confirm" width="455" height="157" class="aligncenter size-full wp-image-129" /></a><br />
<em>Gmail's pops up this prompt when the user attempts to leave the page while drafting an email.</em></p>
<p>Worthy to note, however, is that Opera <a href="http://www.quirksmode.org/bugreports/archives/2004/11/load_and_unload.html">doesn't fire the unload event</a> when the browser refreshes the page, or uses the back/forward buttons to browse off of the page (I had no success with the fix posted in the comments on that page).  What's worse, Opera never fires the onbeforeunload event.  This creates a serious problem with attempting to save page state prior to a user leaving your page.</p>
<p>Browser support aside, I believe that the onbeforeunload prompt is not an ideal way to protect the user from lost work (or unsaved page state).  Humanized has argued, and I agree, that <a href="http://www.alistapart.com/articles/neveruseawarning">an undo operation is much easier on the end user than a warning message</a>.  The strange thing is, Gmail could save the draft in a synchronous Ajax request in the onunload event.  They aren't using the prompt to save Opera users from losing their drafts, since the Opera web browser doesn't even fire the onbeforeunload event.  (Interestingly enough, they are using some sort of browser history management to fire a warning to the user when they press back, or forward, in Opera -- but Reload can't be caught using this method, so your could draft email be lost).</p>
<p>From a User Interface design standpoint, I would recommend just sticking with onunload.  You can still perform your synchronous Ajax call in the method to save the state of your page, so that the user can later resume their state or undo the operation. (Except for Back/Forward/Refresh in Opera, until they support a better onunload or any onbeforeunload).  The onbeforeunload prompt is an unnecessary evil, and doesn't do much besides annoy the end user with another warning message and a mouse click.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/JavaScript" rel="tag">JavaScript</a>, <a href="http://technorati.com/tag/onunload" rel="tag"> onunload</a>, <a href="http://technorati.com/tag/onbeforeunload" rel="tag"> onbeforeunload</a>, <a href="http://technorati.com/tag/Ajax" rel="tag"> Ajax</a>, <a href="http://technorati.com/tag/Undo" rel="tag"> Undo</a>, <a href="http://technorati.com/tag/Opera" rel="tag"> Opera</a>, <a href="http://technorati.com/tag/Gmail" rel="tag"> Gmail</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/04/22/dont-let-the-door-hit-you-onunload-and-onbeforeunload/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Forgive My Feed</title>
		<link>http://www.zachleat.com/web/2008/04/18/forgive-my-feed/</link>
		<comments>http://www.zachleat.com/web/2008/04/18/forgive-my-feed/#comments</comments>
		<pubDate>Sat, 19 Apr 2008 04:56:57 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[Other]]></category>

		<category><![CDATA[Self]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=128</guid>
		<description><![CDATA[This is going through a bit of maintenance.  I'm tagging and recategorizing my old posts, so feel free to "mark all as read" if you get a bunch of new items.
]]></description>
			<content:encoded><![CDATA[<p>This is going through a bit of maintenance.  I'm tagging and recategorizing my old posts, so feel free to "mark all as read" if you get a bunch of new items.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/04/18/forgive-my-feed/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rethinking JavaScript Grids and DataTables</title>
		<link>http://www.zachleat.com/web/2008/04/13/rethinking-javascript-grids-and-datatables/</link>
		<comments>http://www.zachleat.com/web/2008/04/13/rethinking-javascript-grids-and-datatables/#comments</comments>
		<pubDate>Sun, 13 Apr 2008 20:29:26 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[Interface Design]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Conservative Design]]></category>

		<category><![CDATA[Dojo]]></category>

		<category><![CDATA[ExtJS]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=122</guid>
		<description><![CDATA[In the world of front end engineering, one must consider the end-user of the interface first, and above all other things.  The priorities should not start with development ease, nor external library preference.  The priorities should start with the needs of the consumer of your end product.
Evolution of your engineering skill is also [...]]]></description>
			<content:encoded><![CDATA[<p>In the world of front end engineering, one must consider the end-user of the interface first, and above all other things.  The priorities should not start with development ease, nor external library preference.  The priorities should start with the needs of the consumer of your end product.</p>
<p>Evolution of your engineering skill is also a vital trait in this world, which means that as a developer increases his knowledge of good practices and proper methods, sometimes he must shirk his previous assertions about the world as he previously knew it.  And today I'm shirking a staple of the front end as all web users know it: The Grid (DataTable) Component.</p>
<p>Of course, I've written a few articles in the past about the <a href="http://developer.yahoo.com/yui/datatable/">YUI DataTable</a>, during my long love affair with Yahoo's User Interface library.  Another popular one is jQuery's <a href="http://tablesorter.com/docs/">TableSorter</a>.  Then there's the <a href="http://dojotoolkit.org/book/dojo-book-0-9/docx-documentation-under-development/grid">Dojo Grid</a>, a component <a href="http://www.sitepen.com/blog/2007/09/16/the-dojo-grid/">inherited from TurboAjax</a>.  ExtJS has a variety of nice examples as well for their <a href="http://extjs.com/deploy/dev/examples/#sample-1">Ext 2.0 Grid</a>.</p>
<p>And after using these Grids and DataTables, I certainly respect the programming that went into developing these components.  But let's take a step back for a second.  Why do the users need the bells and whistles in these components?  Are they worth the extra load time and complexity they add to the interface?</p>
<p>All we're doing here is putting a nice coat of paint on a &lt;table&gt; tag.  Sure, it might have some nice ancillary features like Ajax Data Loading, but those don't really matter - they are things that can be easily performed with some good Ajax and DOM insert utility functions.  In fact, most of the core features included in these components could be described as feature creep, and not beneficial to the end user at all.  Feature creep contributes to code bloat, which means the user is downloading bytes to their web browser that they don't need, which can hamper performance.  Libraries usually have online examples of their components, and the include sizes are seen below.  (Gzip compression not considered)</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>JavaScript Size</th>
<th>Minimized</th>
<th>Link</th>
</tr>
</thead>
<tbody>
<tr>
<td>YUI DataTable</td>
<td>216.6 KB</td>
<td>Minimized</td>
<td><a href="http://developer.yahoo.com/yui/examples/datatable/dt_basic_clean.html">Example</a></td>
</tr>
<tr>
<td>Dojo Grid</td>
<td>338.4 KB</td>
<td>Unminimized</td>
<td><a href="http://dojotoolkit.org/book/dojo-book-0-9/docx-documentation-under-development/grid/simple-grid">Example</a></td>
</tr>
<tr>
<td>Ext Grid</td>
<td>545.5 KB</td>
<td>Minimized</td>
<td><a href="http://extjs.com/deploy/dev/examples/grid/array-grid.html">Example</a></td>
</tr>
<tr>
<td>jQuery TableSorter</td>
<td>66 KB</td>
<td>Minimized</td>
<td><a href="http://www.tablesorter.com/">Example</a></td>
</tr>
</tbody>
</table>
<p>The JavaScript include sizes listed above are directly proportional to the feature set that the components provide, and should give you an idea of the overhead involved with using them.  Do we need 545.5 KB of features coming down the pipe to give our users an extra bell, or an extra whistle?  Let's analyze the features to rationalize their usage, and remove items from the feature set.</p>
<ul>
<li>Sorting</li>
<li>Modifying column order and display</li>
<li>Resizing columns</li>
<li>Editing of row data directly on the grid itself</li>
<li>Scrolling</li>
<li>Pagination</li>
</ul>
<p><strong>Sorting</strong></p>
<p>Data should be used in the context of its usefulness.  You have a list of messages in your e-mail inbox.  What's the most useful context for this list?  In order of date received.  The default sort order provided by the application, to facilitate proper use of the application.  Is comparing the rows in the grid by any other method as useful?  Does the user need to see the list of messages ordered alphabetically by subject?  In these cases where the user is in need of a specific message, <em>searching and filtering</em> is more useful than sorting.  The default sort is useful, but allowing the user to resort on the client, in most cases, is not as useful as other methods of finding a row.</p>
<p><strong>Modifying column order and display</strong></p>
<p>The same argument can be made for any of the other methods of customization provided to the end user.  Does the user need to reorder or hide columns?  The context provided by the application should be sufficient to use the applications data in the way it was intended.  Don't overcomplicate your user interface with needless features or a deluge of useless data.  Provide succinct, appropriate data, and the user needn't reorder or change the interface.</p>
<p><strong>Resizing columns</strong></p>
<p>The default HTML &lt;table&gt; tag expands to fit the data inside of its cells.  Even when you set the width of the table explicitly, the cells adjust themselves accordingly to fit the data.  This should be the behavior of your table.  You needn't monkey around with widths, the browser is smart enough to do it for you.  You can even customize a cell to wrap its text to multiple lines with CSS, if need be.</p>
<p><strong>Editing of row data directly on the grid itself</strong></p>
<p>If you're providing an Excel spreadsheet interface for the end user to customize your data, you haven't designed your interface correctly.  Rethink how the user needs to interact with the data you've provided, and give them a better, simpler way to edit the data.</p>
<p><strong>Scrolling</strong></p>
<p>Everyone knows that internal scrollbars on a page are evil.  I don't even like scrollbars on textareas, to be honest.  Previously, I had worked and reworked the YUI DataTable to handle horizontal scrolling.  Looking back on this, it was a mistake.  There are better ways to handle lots of data in a table, without the heavy mouse interaction and scanning that scrolling require.  Which brings me to my next point.</p>
<p><strong>Pagination</strong></p>
<p>This is the one exception to the feature set cutting board.  This is the one feature that's is a requirement, when the data set has too many records to fit on a single page.</p>
<p>Keep these in mind, and look at the feature set provided by a few sites using tabular data centric interfaces that know a thing or two about interface design:</p>
<p><a href='http://www.zachleat.com/web/2008/04/13/rethinking-javascript-grids-and-datatables/gmail/' title='Google Mail'><img src="http://www.zachleat.com/web/wp-content/uploads/2008/04/gmail-150x150.png" width="150" height="150" class="attachment-thumbnail" /></a><br />
<a href='http://www.zachleat.com/web/2008/04/13/rethinking-javascript-grids-and-datatables/wordpress-admin/' title='Wordpress 2.5 Admin Interface'><img src="http://www.zachleat.com/web/wp-content/uploads/2008/04/wordpress-admin-150x150.png" width="150" height="150" class="attachment-thumbnail" /></a><br />
<a href='http://www.zachleat.com/web/2008/04/13/rethinking-javascript-grids-and-datatables/google-reader/' title='Google Reader List View'><img src="http://www.zachleat.com/web/wp-content/uploads/2008/04/google-reader-150x150.png" width="150" height="150" class="attachment-thumbnail" /></a></p>
<p><strong>So, what should we include?</strong></p>
<p>A simple CSS class to style your table is sufficient, with links to paginate the table (properly) and/or a hover for row selection if needed.  You're looking at 10-20 lines of jQuery code, maximum, and a few CSS declarations.  In lieu of sorting, of course, you'll need to program in a mechanism for searching and filtering as well.  But really, the difficulty with programming this component is knowing what to leave out.</p>
<p>Technorati Tags: <a href="http://technorati.com/tag/Interface+Design" rel="tag">Interface Design</a>, <a href="http://technorati.com/tag/Dojo" rel="tag"> Dojo</a>, <a href="http://technorati.com/tag/Ext" rel="tag"> Ext</a>, <a href="http://technorati.com/tag/jQuery" rel="tag"> jQuery</a>, <a href="http://technorati.com/tag/YUI" rel="tag"> YUI</a>, <a href="http://technorati.com/tag/Grid" rel="tag"> Grid</a>, <a href="http://technorati.com/tag/DataTable" rel="tag"> DataTable</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/04/13/rethinking-javascript-grids-and-datatables/feed/</wfw:commentRss>
		</item>
		<item>
		<title>ALARMd 2 Beta, with Google Calendar Integration</title>
		<link>http://www.zachleat.com/web/2008/04/06/alarmd-2-beta-with-google-calendar-integration/</link>
		<comments>http://www.zachleat.com/web/2008/04/06/alarmd-2-beta-with-google-calendar-integration/#comments</comments>
		<pubDate>Sun, 06 Apr 2008 07:31:59 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[Interface Design]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Projects]]></category>

		<category><![CDATA[Alarmd]]></category>

		<category><![CDATA[Google Calendar]]></category>

		<category><![CDATA[jQuery]]></category>

		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=111</guid>
		<description><![CDATA[Take a look: ALARMd 2 Beta
Update: added Metric and Unit Circle time formats.
I know, some of you are reading this and thinking to yourself -- genital herpes is more appealing than yet another online alarm clock.  But to that I say, congratulations, that's one of the new features in ALARMd 2!
Why did I make [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.zachleat.com/Projects/alarmd-beta/">Take a look: ALARMd 2 Beta</a></p>
<p><em><strong>Update</strong>: added Metric and Unit Circle time formats.</em></p>
<p>I know, some of you are reading this and thinking to yourself -- genital herpes is more appealing than yet another online alarm clock.  But to that I say, congratulations, that's one of the new features in ALARMd 2!</p>
<p>Why did I make another online alarm clock?  Mostly due to missing features and limitations in the old version, but also because it's a good exercise in JavaScript programming and User Interface design.  Everyone likes to hone their skills, and this is my publicly viewable work desk.  But the real reason I went back to rewrite the old version is that I'm hooked on <a href="http://jquery.com">jQuery</a>.  I can't get enough of that sweet, sweet, source code, and couldn't stand to see my old, crusty, handwritten DOM manipulations polluting web browsers across the world.  Users of the Yahoo User Interface Library (what I used for the original version of ALARMd) would do well to consider jQuery a nice plugin to be used alongside YUI.  It will clean up your code MAX_INT-fold.</p>
<p>Here are a few new features and addressed limitations in ALARMd 2.</p>
<ul>
<li>Easy Alarm Mode: No more fumbling around when you just want one simple easy-to-add alarm.</li>
<li>Google Calendar Alarm Mode: Customize your alarm schedule to your heart's content, it will load your alarms straight from a publicly available Google Calendar.  There are some great features with this:
<ul>
<li>Load only the first calendar event of every day</li>
<li>Day Limiter (Example: Only load calendar events within the next 3 days)</li>
<li>Minute Adjuster (Example: Alarm me 90 minutes before work without adding a separate event)</li>
<li>Google does a nice job of normalizing dates as well, so you don't have to worry about calendar time syncing.  If it says 8AM on your calendar, it's going to alarm you at 8AM on your computer's local time.</li>
</ul>
</li>
<li>New Clock Formats:
<ul>
<li>Human Readable Clock Format: Think "Half Past Two", or "Quarter Til Twelve".  This idea is from <a href="http://www.insightoutsight.co.uk/viewproject.php?cid=2&#038;pid=3&#038;iid=2">Laurence Willmott's Project "It's about Time"</a>.  I took some liberties with his labeling scheme, I hope he doesn't mind too much.</li>
<li><a href="http://zapatopi.net/metrictime/">Metric Time Format</a>: Shows the measurement Centi-days in Local Metric Time.  Basically, it's a percentage of much of the day has passed.  If it's 80.000, 80 percent of the day has passed, which coincides with 7:12 PM.</li>
<li>Unit Circle Time Format: Displays the time in radians that would be shown if a clock were <a href="http://www.cafepress.com/poofietomato.49111330">pasted on top of a unit circle</a>.  If it's 12 o'clock, it will read &pi;/2.  After programming this one, it's starting to seem normal in my brain.  Oh, it's 3&pi;/2?  Time to eat dinner.  How the hell did it get 2&pi;/3??</li>
</ul>
</li>
<li><a href="http://www.zachleat.com/web/2008/03/23/yet-another-pretty-date-javascript/">Human Readable Alarm Dates</a>: Think "29 Minutes", "1 Hour", "2 Days Ago".</li>
<li>Much cleaner interface, using a jQuery accordion to display the options.</li>
<li>The old ALARMd required an internet connection for all sources, and provided no safeguard if your internet went down whilst you were sleeping.  ALARMd 2 preloads all Youtube videos in the background when the page loads using the new <a href="http://apiblog.youtube.com/2008/03/something-to-write-home-about.html">Youtube JavaScript API</a>.  A nice benefit of this is that the browser window no longer requires focus to play the YouTube video.</li>
<li>Less clunky interface for adding new alarm sources.</li>
<li>Repeat option for YouTube videos and MP3's.  Turn infinite loop on or off.  Careful with this one.  Don't leave ALARMd going if you're not going to be home when it goes off.</li>
<li>CSS Skins, Use the really simple ones I've included for Red, Green, or Blue, or include your own URL to your own hosted CSS file.  Have a good skin?  I'll include it in the select list and give you some props here, just link to it in the comments below.  Use some CSS class hooks to spice up your skins (they are mutually exclusive).  These are CSS classes that are added to the body tag to allow you to style the alarm differently depending on the alarm clock's current state.  <em>Future enhancements</em> might include more than just alarm-based hooks: Year, day of the year, and hour of the day might be useful, that way you could style the clock to show a lighter background during the day and a darker background at night.
<ul>
<li>.alarmWithin30Minutes</li>
<li>.alarmWithin15Minutes</li>
<li>.alarmWithin5Minutes</li>
<li>.alarmWithin1Minute</li>
<li>.alarmActive (Alarm is being played)</li>
</ul>
</li>
<li>Still has all the old favorites:
<ul>
<li>Test Button to make sure the video or source is working and to check your volume.</li>
<li>Count Down mode to show the time between now and the first alarm.</li>
<li>Store your own list of alarm sources, using YouTube, MP3, Last.FM, or any URL (Pandora is included).</li>
<li>Military time (24 hour clock) and seconds toggle.</li>
<li>Naked mode (get rid of the extras)</li>
</ul>
</li>
</ul>
<p>Finished reading?  I'm surprised you didn't click the link at the top: <a href="http://www.zachleat.com/Projects/alarmd-beta/">ALARMd 2 Beta</a></p>
<p>Remember, this is BETA.  That means it's new.  I've done my best to test and code out all the kinks, but there may be a few that slipped through.  Try it out and please report any bugs.  And once again, this code is released under the BSD license.</p>
<p>I'll probably move this to the main ALARMd.com domain shortly.</p>
<p>Alarmd has been personally tested with Firefox 2, Firefox 3, Internet Explorer 7, Safari 3.1, and Opera 9.27, all on Windows.  Google GDATA reports an unsupported browser error on Safari and Opera, which you can hide using custom CSS.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/04/06/alarmd-2-beta-with-google-calendar-integration/feed/</wfw:commentRss>
		</item>
		<item>
		<title>20000 Leagues Under the API: YouTube JavaScript</title>
		<link>http://www.zachleat.com/web/2008/04/05/20000-leagues-under-the-api-youtube-javascript/</link>
		<comments>http://www.zachleat.com/web/2008/04/05/20000-leagues-under-the-api-youtube-javascript/#comments</comments>
		<pubDate>Sun, 06 Apr 2008 03:47:33 +0000</pubDate>
		<dc:creator>Zach Leatherman</dc:creator>
		
		<category><![CDATA[CSS]]></category>

		<category><![CDATA[JavaScript]]></category>

		<category><![CDATA[Reviews]]></category>

		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://www.zachleat.com/web/?p=120</guid>
		<description><![CDATA[Today, children, we'll be exploring the wonderful world of the official JavaScript API published by YouTube a few weeks ago.  I read a few interesting posts on the subject when it first came out, and it's been on my list of things to explore for the next (and hopefully last) version of Alarmd. This [...]]]></description>
			<content:encoded><![CDATA[<p>Today, children, we'll be exploring the wonderful world of the official JavaScript API published by YouTube a few weeks ago.  I read a <a href="http://apiblog.youtube.com/2008/03/something-to-write-home-about.html">few</a> <a href="http://blogoscoped.com/archive/2008-03-14-n11.html">interesting</a> <a href="http://www.wait-till-i.com/2008/03/12/video-captioning-made-easy-with-the-youtube-javascript-api/">posts</a> on the subject when it first came out, and it's been on my list of things to explore for the next (and hopefully last) version of <a href="http://www.alarmd.com/">Alarmd</a>. This isn't going to be a long post so much as a laundry list of points worth mentioning and limitations there-of regarding the API itself.</p>
<ol>
<li>If you want to change videos dynamically by loading a new video into an existing player, you must use the Chromeless player (which requires an API key).  The loadVideoById() method is only available in the Chromeless player.  Whatever you do, don't try to dynamically destroy and create a new player, this will cause JavaScript errors in Internet Explorer (although not Firefox).</li>
<li>CSS properties: When the player has the css <code>display: none</code> applied, it will not play.  When the css <code>visibility: hidden</code> is applied, the video will still play, but will not be shown on the screen.  If you wanted a headless player, like what the music search engine <a href="http://humanized.com/weblog/2007/11/13/songza-launch/">Songza</a> does, you'd want to take this approach.  Word of warning, there's some tricky shit going on when you try to dynamically change these properties on a player and run commands on the player at the same time (or close to the same).  For instance, I got into a sticky situation where I'd try to show the player and load a new video into the player in the same method.  I had to separate these with a timeout to get both to run without error.</li>
<li>To load, you must play.  Unfortunately, I wanted to pre-load the video without actually playing the video.  This is unsupported.  To handle this, I had to play, then pause after a timeout (using window.setTimeout).  Not the prettiest, but it seems to work.  Obviously the API in this case has very low cohesion, as the loadVideoById method ALSO plays the video, not simply doing ONLY what the method name suggests.</li>
<li>Forcing a global? When the player first loads after you've used the SWFObject embedSWF() command, it will call the function onYouTubePlayerReady(), which you can't customize.  It must be that function name, and it must be in the global namespace.  Keep in mind that onYouTubePlayerReady() is called every time the player is shown (when it was otherwise hidden using the css <code>display: none</code>)</li>
</ol>
<p>Unfortunately, there is some voodoo going on here that I don't fully understand.  I'm not a flash guru, nor have I ever claimed to be.  But there have been a few bugs in my experience with the API that have led me to believe that it's not quite there yet.  Maybe my use cases were a bit unique, but they weren't that extreme.  I should be able to hide and show the player without error.  I should be able to destroy the player without error.  I should be able to load a video without playing it.</p>
<p>But hey, it works.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zachleat.com/web/2008/04/05/20000-leagues-under-the-api-youtube-javascript/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
