<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>stchur-BLOG &#187; Useful Functions</title>
	<atom:link href="http://blog.stchur.com/category/useful-functions/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.stchur.com</link>
	<description>web / programming / javascript / css / html</description>
	<lastBuildDate>Sat, 16 Jan 2010 01:09:03 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Programmatically clicking a link in Javascript</title>
		<link>http://blog.stchur.com/2010/01/15/programmatically-clicking-a-link-in-javascript/</link>
		<comments>http://blog.stchur.com/2010/01/15/programmatically-clicking-a-link-in-javascript/#comments</comments>
		<pubDate>Sat, 16 Jan 2010 01:09:03 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[Useful Functions]]></category>
		<category><![CDATA[actuate]]></category>
		<category><![CDATA[click]]></category>
		<category><![CDATA[dispatch]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[prevent default action]]></category>
		<category><![CDATA[programmatically clicking]]></category>
		<category><![CDATA[simulate]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/?p=129</guid>
		<description><![CDATA[	More accurately, this would be called actuating a link (i.e. the process of setting the link's behavior into motion, if you will.)  In other words, you have a link:
	&#60;a id = 'bingLink' href = &#34;http://www.bing.com&#34;&#62;Bing&#60;/a&#62;
	And you want to programmatically make that link do its thing.  This usually means having the browser navigate to [...]]]></description>
			<content:encoded><![CDATA[	<p>More accurately, this would be called actuating a link (i.e. the process of setting the link's behavior into motion, if you will.)  In other words, you have a link:</p>
	<div class="dean_ch" style="white-space: nowrap;">&lt;a id = 'bingLink' href = &quot;http://www.bing.com&quot;&gt;Bing&lt;/a&gt;</div>
	<p>And you want to programmatically make that link do its thing.  This usually means having the browser navigate to the URL specified link's href attribute (though, it can also mean executing some click handler if one happens to be specified on said link.)</p>
	<p>To be honest, I don't think there are a ton of real-world uses for this, but there are a few.  And depending on your needs, it may not be trivial to accomplish this in a cross-browser fashion.  For example:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> myLink = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'myLink'</span><span class="br0">&#41;</span>;<br />
myLink.<span class="me1">click</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
	<p>The above will do the trick in IE, because IE supports <code>.click()</code> on links.  Most other browsers don't though, so that's not an all-encompassing solution.</p>
	<p>One (partial) solution in non-IE browsers might be to read the <code>href</code> attribute from a given link and then use Javascript to make the browser navigate to to the URL specified by <code>href</code> that way:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> actuateLink<span class="br0">&#40;</span>link<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp;window.<span class="me1">location</span>.<span class="me1">href</span> = link.<span class="me1">href</span>;<br />
<span class="br0">&#125;</span></div>
	<p>This is not a complete solution for a couple of reasons:</p>
	<ol>
	<li>Navigating by setting <code>window.location.href</code> blows away the <code>document.referrer</code> property.</li>
	<li>Any click event handler wired to the link will not execute.</li>
	</ol>
	<p>For anyone who has read my post about <a href = "http://blog.stchur.com/2007/11/16/re-routing-events-in-javscript/" title = "Re-routing events in Javascript">Re-routing events in Javascript</a> post, you'll know that it is possible to simulate an event though the use of <code>.dispatchEvent(..)</code>.</p>
	<p>Here's a brief refresher of the part most relevant to this discussion:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> myEvt = document.<span class="me1">createEvent</span><span class="br0">&#40;</span><span class="st0">'MouseEvents'</span><span class="br0">&#41;</span>;<br />
myEvt.<span class="me1">initEvent</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp;<span class="st0">'click'</span> &nbsp; &nbsp; &nbsp;<span class="co1">// event type</span><br />
&nbsp; &nbsp;,<span class="kw2">true</span> &nbsp; &nbsp; &nbsp;<span class="co1">// can bubble?</span><br />
&nbsp; &nbsp;,<span class="kw2">true</span> &nbsp; &nbsp; &nbsp;<span class="co1">// cancelable?</span><br />
<span class="br0">&#41;</span>;<br />
document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'myLink'</span><span class="br0">&#41;</span>.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>myEvt<span class="br0">&#41;</span>;</div>
	<p>This approach will ensure that any click event handlers will fire as desired (though, it's worth nothing that you'd have to handle <code>mousedown, mouseup, keydown, keypress</code> etc... separately,) but it does NOT actuate the link!</p>
	<p>This might surprise you.  Dispatching a click event to a link doesn't actually cause the browser to navigate to the URL specified by that link's href property.  This actually isn't shocking to me, personally.  A little surprising, but not shocking.</p>
	<p>Anyway, one option is to dispatch the click event and then use <code>window.location.href</code>.  This should achieve (some of) the desired effect, but again, the <code>document.referrer</code> will not be preserved if you do this.  Also, if the event handler <a href = "http://blog.stchur.com/2006/06/23/preventing-the-default-action/" title = "Preventing the default action">prevents the default action</a>, this method will not honor the code that prevents the default action (i.e. the link will navigate despite the code that attempts to prevent it from doing so.)</p>
	<p>You can work around the <code>window.location.href</code> problem by creating a &lt;form&gt; element, settings its <code>action</code> attribute to that of the link's href attribute and then submitting the form through <code>myForm.submit()</code>, but the problem regarding preventing the default action remains.</p>
	<h2>A 95% Solution</h2>
	<p>Is there a 100% perfect solution to this problem?  Probably, but I'm not 100% perfect.  I'm only 95% perfect, so I give you my 95% solution:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> actuateLink<span class="br0">&#40;</span>link<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> allowDefaultAction = <span class="kw2">true</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>link.<span class="me1">click</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;link.<span class="me1">click</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>document.<span class="me1">createEvent</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> e = document.<span class="me1">createEvent</span><span class="br0">&#40;</span><span class="st0">'MouseEvents'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">initEvent</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; <span class="st0">'click'</span> &nbsp; &nbsp; <span class="co1">// event type</span><br />
&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ,<span class="kw2">true</span> &nbsp; &nbsp; &nbsp;<span class="co1">// can bubble?</span><br />
&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; ,<span class="kw2">true</span> &nbsp; &nbsp; &nbsp;<span class="co1">// cancelable?</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;allowDefaultAction = link.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>allowDefaultAction<span class="br0">&#41;</span>&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> f = document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'form'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;f.<span class="me1">action</span> = link.<span class="me1">href</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;document.<span class="me1">body</span>.<span class="me1">appendChild</span><span class="br0">&#40;</span>f<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;f.<span class="me1">submit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
	<p>To use it:</p>
	<div class="dean_ch" style="white-space: nowrap;">actuateLink<span class="br0">&#40;</span>document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'bingLink'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
	<p>This code is self explanatory, right?</p>
	<p>If <code>.click()</code> is available, let's use that.  If not, let's try to do a W3C-style create and dispatch event.  Then, in order to maintain the <code>document.referrer</code> property, we'll use a form submission, but we only want to submit that form if the event handler (if there is one) for the <code>click</code> event doesn't explicitly prevent the default action.</p>
	<p>This isn't a 100% perfect solution because, actuating a link in this manner is only going to invoke click handlers and navigate to the URL of the link's href attribute (if appropriate to do so.)  It isn't going to invoke handlers for any other types of events.  And I'm not about to create and dispatch every possible kind of event.  Besides, I think we can all agree that <code>click</code> is by far the most common scenario.</p>
	<p>So there ya go.  Programmatically clicking (or more accurately, actuating) a link with Javascript.  Enjoy!</p>
	<p>(Tested: Firefox 3.5.7, IE8, Opera 10.01, Safari/Win 4.0.3, Chrome 3)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2010/01/15/programmatically-clicking-a-link-in-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Ultimate addEvent(..) function</title>
		<link>http://blog.stchur.com/2008/09/25/the-ultimate-addevent-function/</link>
		<comments>http://blog.stchur.com/2008/09/25/the-ultimate-addevent-function/#comments</comments>
		<pubDate>Thu, 25 Sep 2008 18:32:17 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Beating IE into submission]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[Firefox Related]]></category>
		<category><![CDATA[Useful Functions]]></category>
		<category><![CDATA[Gimme]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Ultimate addEvent]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/09/25/the-ultimate-addevent-function/</guid>
		<description><![CDATA[	Two articles in particular that I've written on this blog have garnered a lot of positive feedback.
	
	Fixing IE's attachEvent Failures
	mouseenter and mouseleave Events for Firefox (and other Non-IE Browsers)
	
	As time has gone on, I've seen mention of these articles pop up in programming forums here and there, and they still receive comments from time to [...]]]></description>
			<content:encoded><![CDATA[	<p>Two articles in particular that I've written on this blog have garnered a lot of positive feedback.</p>
	<ol>
	<li><a href = "http://blog.stchur.com/2006/10/12/fixing-ies-attachevent-failures/" title = "Fixing IE's attachEvent Failures">Fixing IE's attachEvent Failures</a></li>
	<li><a href = "http://blog.stchur.com/2007/03/15/mouseenter-and-mouseleave-events-for-firefox-and-other-non-ie-browsers/" title = "mouseenter and mouseleave Events for Firefox (and other Non-IE Browsers)">mouseenter and mouseleave Events for Firefox (and other Non-IE Browsers)</a></li>
	</ol>
	<p>As time has gone on, I've seen mention of these articles pop up in programming forums here and there, and they still receive comments from time to time, which lets me know that people are still getting something out of them.</p>
	<p>Unfortunately, the code in them is a tad dated.  I've learned more and improved my code since I originally wrote them, and while these improvements have made their way into my <a href = "http://gimme.stchur.com" title = "The Gimme Javascript Library">Javascript Library</a>, I know that the majority of people are just grabbing the code directly from the blog entries.</p>
	<p>So I've decided to post an update: a sort of fusion between these two blog entries which offers functionality for addressing all of the issues discussed in the aforementioned entries (and then some).</p>
	<p>I consider this new function the "Ultimate addEvent Function" because I really believe it addresses the large majority of cross-browser issues that people face when dealing with events in Javascript.  And furthermore, this function goes beyond anything that any other Javascript library provides (at least as far as I know).</p>
	<p>So without further ado, I offer to you:</p>
	<h3>sstchur's Ultimate addEvent(..) function!</h3></p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> xb = <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
<span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> GUIDCounter = <span class="nu0">0</span>;<br />
&nbsp; &nbsp;<span class="kw2">var</span> evtHash = <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;<span class="kw2">var</span> pseudoEvents =<br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="st0">'mouseenter'</span>: <span class="kw2">function</span><span class="br0">&#40;</span>_fn, _useCapture, _listening<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> f = mouseEnter<span class="br0">&#40;</span>_fn<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_listening ?<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;xb.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="kw1">this</span>, <span class="st0">'mouseover'</span>, f, _useCapture, <span class="kw2">false</span><span class="br0">&#41;</span> :<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;xb.<span class="me1">removeEvent</span><span class="br0">&#40;</span><span class="kw1">this</span>, <span class="st0">'mouseover'</span>, f, _useCapture, <span class="kw2">false</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;f = <span class="kw2">null</span>;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span>,<br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="st0">'mouseleave'</span>: <span class="kw2">function</span><span class="br0">&#40;</span>_fn, _useCapture, _listening<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> f = mouseEnter<span class="br0">&#40;</span>_fn<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_listening ?<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;xb.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="kw1">this</span>, <span class="st0">'mouseout'</span>, f, _useCapture, <span class="kw2">false</span><span class="br0">&#41;</span> :<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;xb.<span class="me1">removeEvent</span><span class="br0">&#40;</span><span class="kw1">this</span>, <span class="st0">'mouseout'</span>, f, _useCapture, <span class="kw2">false</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;f = <span class="kw2">null</span>;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;xb.<span class="me1">Helper</span> =<br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;getObjectGUID: getObjectGUID,<br />
&nbsp; &nbsp;&nbsp; &nbsp;storeHandler: storeHandler,<br />
&nbsp; &nbsp;&nbsp; &nbsp;retrieveHandler: retrieveHandler,<br />
&nbsp; &nbsp;&nbsp; &nbsp;isAnAncestorOf: isAnAncestorOf,<br />
&nbsp; &nbsp;&nbsp; &nbsp;mouseEnter: mouseEnter<br />
&nbsp; &nbsp;<span class="br0">&#125;</span>;&nbsp;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;xb.<span class="me1">addEvent</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> document.<span class="me1">addEventListener</span> !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> w3c_addEvent;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> document.<span class="me1">attachEvent</span> !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> ie_addEvent;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// no modern event support I guess <img src='http://blog.stchur.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// (you could use DOM 0 here if you really wanted to)</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">function</span> w3c_addEvent<span class="br0">&#40;</span>_elem, _evtName, _fn, _useCapture, _directCall<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> eventFn = pseudoEvents<span class="br0">&#91;</span>_evtName<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> eventFn === <span class="st0">'function'</span> &amp;&amp; _directCall !== <span class="kw2">false</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;eventFn.<span class="me1">call</span><span class="br0">&#40;</span>_elem, _fn, _useCapture, <span class="kw2">true</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_elem.<span class="me1">addEventListener</span><span class="br0">&#40;</span>_evtName, _fn, _useCapture<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">function</span> ie_addEvent<span class="br0">&#40;</span>_elem, _evtName, _fn, _useCapture, _directCall<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> eventFn = pseudoEvents<span class="br0">&#91;</span>_evtName<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> eventFn === <span class="st0">'function'</span> &amp;&amp; _directCall !== <span class="kw2">false</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;eventFn.<span class="me1">call</span><span class="br0">&#40;</span>_elem, _fn, _useCapture, <span class="kw2">true</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// create a key to identify this element/event/function combination</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> key = generateHandlerKey<span class="br0">&#40;</span>_elem, _evtName, _fn<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// if this element/event/combo has already been wired up, just return</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> f = evtHash<span class="br0">&#91;</span>key<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> f !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// create a helper function to fix IE's lack of standards support</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;f = <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// map .target to .srcElement</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">target</span> = e.<span class="me1">srcElement</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// map .relatedTarget to either .toElement or .fromElement</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>_evtName == <span class="st0">'mouseover'</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> e.<span class="me1">relatedTarget</span> = e.<span class="me1">fromElement</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>_evtName == <span class="st0">'mouseout'</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> e.<span class="me1">relatedTarget</span> = e.<span class="me1">toElement</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">preventDefault</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> e.<span class="me1">returnValue</span> = <span class="kw2">false</span>; <span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">stopPropagation</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> e.<span class="me1">cancelBubble</span> = <span class="kw2">true</span>; <span class="br0">&#125;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// call the actual function, using entity (the element) as the 'this' object</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_fn.<span class="me1">call</span><span class="br0">&#40;</span>_elem, e<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// null out these properties to prevent memory leaks</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">target</span> = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">relatedTarget</span> = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">preventDefault</span> = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">stopPropagation</span> = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;e = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// add the helper function to the event hash</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;evtHash<span class="br0">&#91;</span>key<span class="br0">&#93;</span> = f;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// hook up the event (IE style)</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_elem.<span class="me1">attachEvent</span><span class="br0">&#40;</span><span class="st0">'on'</span> + _evtName, f<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;key = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;f = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="br0">&#125;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;xb.<span class="me1">defineEvent</span> = <span class="kw2">function</span><span class="br0">&#40;</span>_evtName, _logicFn<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;pseudoEvents<span class="br0">&#91;</span>_evtName<span class="br0">&#93;</span> = _logicFn;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span>;</p>
	<p>&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="co1">// Helper Functions</span><br />
&nbsp; &nbsp;<span class="kw2">function</span> storeHandler<span class="br0">&#40;</span>_key, _handler<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;evtHash<span class="br0">&#91;</span>_key<span class="br0">&#93;</span> = _handler;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">function</span> retrieveHandler<span class="br0">&#40;</span>_key<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> evtHash<span class="br0">&#91;</span>_key<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">function</span> generateHandlerKey<span class="br0">&#40;</span>_elem, _evtName, _handler<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="st0">'{'</span> + getObjectGUID<span class="br0">&#40;</span>_elem<span class="br0">&#41;</span> + <span class="st0">'/'</span> + _evtName + <span class="st0">'/'</span> + getObjectGUID<span class="br0">&#40;</span>_handler<span class="br0">&#41;</span> + <span class="st0">'}'</span>;&nbsp;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">function</span> isAnAncestorOf<span class="br0">&#40;</span>_ancestor, _descendant, _generation<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>_ancestor === _descendant<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span> <span class="kw2">false</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> gen = <span class="nu0">0</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">while</span> <span class="br0">&#40;</span>_descendant &amp;&amp; _descendant != _ancestor<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;gen++;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_descendant = _descendant.<span class="me1">parentNode</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;_generation = _generation || gen;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> _descendant === _ancestor &amp;&amp; _generation === gen;&nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">function</span> mouseEnter<span class="br0">&#40;</span>_fn<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span>&nbsp; <br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> key = xb.<span class="me1">Helper</span>.<span class="me1">getObjectGUID</span><span class="br0">&#40;</span>_fn<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> f = evtHash<span class="br0">&#91;</span>key<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> f === <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;f = evtHash<span class="br0">&#91;</span>key<span class="br0">&#93;</span> = <span class="kw2">function</span><span class="br0">&#40;</span>_evt<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> relTarget = _evt.<span class="me1">relatedTarget</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">this</span> === relTarget || isAnAncestorOf<span class="br0">&#40;</span><span class="kw1">this</span>, relTarget<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw1">return</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_fn.<span class="me1">call</span><span class="br0">&#40;</span><span class="kw1">this</span>, _evt<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> f;&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="kw2">function</span> getObjectGUID<span class="br0">&#40;</span>_elem<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>_elem === window<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="st0">'theWindow'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span>_elem === document<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="st0">'theDocument'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> _elem.<span class="me1">uniqueID</span> !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> _elem.<span class="me1">uniqueID</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> ex = <span class="st0">'__$$GUID$$__'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> _elem<span class="br0">&#91;</span>ex<span class="br0">&#93;</span> === <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_elem<span class="br0">&#91;</span>ex<span class="br0">&#93;</span> = ex + GUIDCounter++;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> _elem<span class="br0">&#91;</span>ex<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p><span class="br0">&#125;</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
	<div class = "note">The code above, as is, won't work "out of the box" because (for the sake of brevity) I have not included the <code>xb.removeEvent(..)</code> function.  Fear not however.  There will be a link to a download of the full source code, complete with both <code>xb.addEvent(..)</code> and <code>xb.removeEvent(..)</code> at the end of this post.</div>
	<h3>Commentary</h3>
	<p>So some of you may be wondering: "Why <em>another</em> addEvent function.  Haven't we been through this?"  We have, but I think you'll find that this version does more than any other addEvent function you've seen.  For example:</p>
	<ul>
	<li>Works in all browsers that matter</li>
	<li>Ensures <em>one</em> event wire up for any given element/event/handler combination (this is mostly for IE)</li>
	<li>Forces IE to honor the <code>this</code> keyword from within event handler functions</li>
	<li>Normalizes the wire up mechanism in all browsers (no need to include the "on" prefix for IE)</li>
	<li>Forces IE to recognize the following properties/methods on event objects: <code>.stopPropagation()</code>, <code>.preventDefault()</code>, <code>.target</code>, <code>.relatedTarget</code></li>
	<li>Enhances Non-IE browsers to support <code>mouseenter</code> and <code>mouseleave</code> events</li>
	<li>Provides an extension mechanism so developers can write their own custom events that plug right in ('mousewheel' or 'DOMContentReady' for example)</li>
	</ul>
	<p>Given all that the Ultimate addEvent function does, it's not surprising that it has a bit of length to it.  But it isn't super long, and I think it's well worth it.</p>
	<h3>Usage</h3>
	<p>Using the function(s) is just as easy as you'd expect:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> myDiv = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'myDiv'</span><span class="br0">&#41;</span>;<br />
xb.<span class="me1">addEvent</span><span class="br0">&#40;</span>myDiv, <span class="st0">'click'</span>, clickHandler<span class="br0">&#41;</span>;</p>
	<p><span class="kw2">function</span> clickHandler<span class="br0">&#40;</span>e<span class="br0">&#41;</span></p>
	<p>
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'The this keywords works (even in IE!): '</span> + <span class="kw1">this</span>.<span class="me1">id</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<h3>Extending Functionality</h3>
	<p>Since I mentioned that it was possible to extend the Ultimate addEvent function with custom events that plug right in, I figure I'd better offer an example.  Actually, there already is an example built right into it.  Both the <code>mouseenter</code> and <code>mouseleave</code> events utilize the extension mechanism internally, but for demonstration purposes, let's go ahead and add a <code>mousewheel<code> event:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="co1">// Extend the Ultimate addEvent function to recognize a &quot;mousewheel&quot; event</span><br />
xb.<span class="me1">defineEvent</span><span class="br0">&#40;</span><span class="st0">'mousewheel'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>_fn, _useCapture, _listening<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// event name for IE, Opera and Safari</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> evtName = <span class="st0">'mousewheel'</span>;</p>
	<p>&nbsp; &nbsp;<span class="co1">// hander for IE, Opera, and Safari</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> f = _fn;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="co1">// if we're dealing with a Gecko browser, the event name</span><br />
&nbsp; &nbsp;<span class="co1">// and handler need some adjustment</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> ua = navigator.<span class="me1">userAgent</span>.<span class="me1">toLowerCase</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>ua.<span class="me1">indexOf</span><span class="br0">&#40;</span><span class="st0">'khtml'</span><span class="br0">&#41;</span> === <span class="nu0">-1</span> &amp;&amp; ua.<span class="me1">indexOf</span><span class="br0">&#40;</span><span class="st0">'gecko'</span><span class="br0">&#41;</span> !== <span class="nu0">-1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;evtName = <span class="st0">'DOMMouseScroll'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;f = mouseWheel<span class="br0">&#40;</span>_fn<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="co1">// _listening represents whether this is an event attachment or detachment</span><br />
&nbsp; &nbsp;<span class="co1">// that 5th parameter? &nbsp;Don't worry about it; just always use false</span><br />
&nbsp; &nbsp;_listening ? xb.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="kw1">this</span>, evtName, f, _useCapture, <span class="kw2">false</span><span class="br0">&#41;</span> : xb.<span class="me1">removeEvent</span><span class="br0">&#40;</span><span class="kw1">this</span>, evtName, f, _useCapture, <span class="kw2">false</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</p>
	<p><span class="co1">// Helper function for dealing with mousewheel in Gecko browsers</span><br />
<span class="kw2">function</span> mouseWheel<span class="br0">&#40;</span>_fn<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> key = xb.<span class="me1">Helper</span>.<span class="me1">getObjectGUID</span><span class="br0">&#40;</span>_fn<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw2">var</span> f = xb.<span class="me1">Helper</span>.<span class="me1">retrieveHandler</span><span class="br0">&#40;</span>key<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> f === <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;f = <span class="kw2">function</span><span class="br0">&#40;</span>_evt<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_evt.<span class="me1">wheelDelta</span> = -<span class="br0">&#40;</span>_evt.<span class="me1">detail</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_fn.<span class="me1">call</span><span class="br0">&#40;</span><span class="kw1">this</span>, _evt<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;_evt.<span class="me1">wheelDelta</span> = <span class="kw2">null</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;xb.<span class="me1">Helper</span>.<span class="me1">storeHandler</span><span class="br0">&#40;</span>key, f<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="kw1">return</span> f;<br />
<span class="br0">&#125;</span></div>
	<p>I'm glossing over some details here because I don't want this post to get bogged down in something that it isn't really about, but I trust you get the idea.</p>
	<p>Most of this code actually comes from the <a href = "http://gimme.stchur.com" title = "The Gimme Javascript Library">The Gimme Javascript Library</a>.  If you're using Gimme in any of your web pages, you already have all of this functionality for free.  The syntax is a touch different, but all the capabilities are the same.</p>
	<p>And if you happen to be the author of a Live Maps Mashup, you already have Gimme, as the latest version shipped with the most recent <a href = "http://dev.virtualearth.net" title = "Virtual Earth MapControl Developers">Virtual Earth MapControl</a>.</p>
	<p><a name="end"></a></p>
	<h3>Complete Source</h3>
	<p>As promised, here is the <a href = "http://blog.stchur.com/blogcode/ultimate_addevent/ultimate.zip" title = "The Ultimate addEvent function">complete source</a>, including both <code>xb.addEvent(..)</code> and <code>xb.removeEvent(..)</code></p>
	<p>Enjoy! And please don't hesitate to send your feedback, both good and bad (I'm very willing to address issues or try to make requested enhancements).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/09/25/the-ultimate-addevent-function/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>CSS Word-wrap: break word; (revisited)</title>
		<link>http://blog.stchur.com/2008/06/29/css-word-wrap-break-word-revisited/</link>
		<comments>http://blog.stchur.com/2008/06/29/css-word-wrap-break-word-revisited/#comments</comments>
		<pubDate>Mon, 30 Jun 2008 00:16:30 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[Firefox Related]]></category>
		<category><![CDATA[MiniPosts]]></category>
		<category><![CDATA[Mozilla-specific]]></category>
		<category><![CDATA[Useful Functions]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/06/29/css-word-wrap-break-word-revisited/</guid>
		<description><![CDATA[HedgerWow is a great blog.  If you've never checked it out, you definitely should.

I just noticed the other day that his latest post gives some props to my Emulating CSS word-wrap for Mozilla/Firefox blog post, but his version adds some much needed cross-browser support for browsers I neglected.

Nice One, HedgerWow!]]></description>
			<content:encoded><![CDATA[<p><a href = "http://www.hedgerwow.com" title = "Keep It Simple, Stupid">HedgerWow</a> is a great blog.  If you've never checked it out, you definitely should.</p>

<p>I just noticed the other day that his latest post gives some props to my <a href = "http://blog.stchur.com/2007/03/01/word-wrap-for-mozilla-take-2/" title = "Emulating CSS word-wrap for Mozilla/Firefox">Emulating CSS word-wrap for Mozilla/Firefox</a> blog post, but <a href = "http://www.hedgerwow.com/360/dhtml/css-word-break.html" title = "Cross Browser Word Breaker">his version</a> adds some much needed cross-browser support for browsers I neglected.</p>

<p><a href = "http://www.hedgerwow.com/360/dhtml/css-word-break.html" title = "Cross Browser Word Breaker">Nice One</a>, HedgerWow!</p>]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/06/29/css-word-wrap-break-word-revisited/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Palindromes</title>
		<link>http://blog.stchur.com/2008/06/14/palindromes/</link>
		<comments>http://blog.stchur.com/2008/06/14/palindromes/#comments</comments>
		<pubDate>Sat, 14 Jun 2008 19:06:11 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Javascript basics]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Useful Functions]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[palindrome]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/06/14/palindromes/</guid>
		<description><![CDATA[	The other evening while I was watching TV, I happened to have my laptop out, so I started dabbling around in Firebug just for the heck of it.  I'll often just start writing functions for no particular reason, other than to refresh my skills or perhaps discover something about Javascript that I hadn't previously [...]]]></description>
			<content:encoded><![CDATA[	<p>The other evening while I was watching TV, I happened to have my laptop out, so I started dabbling around in Firebug just for the heck of it.  I'll often just start writing functions for no particular reason, other than to refresh my skills or perhaps discover something about Javascript that I hadn't previously known.</p>
	<p>So I was monkeying around, and I decided to write a function to determine if a string were a <a href = "http://en.wikipedia.org/wiki/Palindrome" title = "Wikipedia: Palindrome">palindrome</a>.  This is not a very difficult problem, but it might make for a descent introductory interview question (one of those questions you'd ask to rule out the truly inept).</p>
	<p>With problems like this, I'm mostly interested in two things:</p>
	<ol>
	<li>Writing the function in a clever way, so as to achieve the least amount of code possible</li>
	<li>Writing the function in the most efficient way possible</li>
	</ol>
	<p>Now, if it were Ruby, writing the clever solution (which might also happen to be the most efficient solution in that language -- not sure) would be ridiculously easy:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw1">def</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
&nbsp; &nbsp;s == s.<span class="me1">reverse</span><br />
<span class="kw1">end</span></div>
	<p>That's so trivial, it's probably not even worth writing.</p>
	<p>But Javascript doesn't have a .reverse() method on strings, so you have to take an extra step (still pretty easy though):</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">return</span> s === s.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">reverse</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<p>Split the string into an array, reverse the array, and then join it back together.  Since this is all native Javascript stuff, it turns out to be reasonably fast, though one might expect you could do better.</p>
	<p>For grins and giggles, I decided to see how a manual solution, where I compare characters starting at each end of the string and work towards the middle, would compare:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> i, j,<br />
&nbsp; &nbsp;len = s.<span class="me1">length</span>,<br />
&nbsp; &nbsp;mid = Math.<span class="me1">floor</span><span class="br0">&#40;</span>len / <span class="nu0">2</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;<span class="kw1">for</span> <span class="br0">&#40;</span>i = <span class="nu0">0</span>, j = len - <span class="nu0">1</span>; i &lt; mid; i++, j--<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>s.<span class="me1">charAt</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span> !== s.<span class="me1">charAt</span><span class="br0">&#40;</span>j<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></div>
	<p>This function will probably fail quickly, so that's good, but it also turns out to be generally faster than the split/reverse/join version.  It makes sense, since you're going through the string only one time and twice as fast as normal since you're traversing from both ends at the same time.</p>
	<p>Can you do even better though?  Maybe.  At least in Firefox you can, and quick tests seemed to confirm across other browsers too (but I didn't test extensively).</p>
	<p>What if we split the string in half, and only reverse half of it.  Then we can compare the first half with the original half:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> pal<span class="br0">&#40;</span>s<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> len = s.<span class="me1">length</span>,<br />
&nbsp; &nbsp;x = len / <span class="nu0">2</span>,<br />
&nbsp; &nbsp;y = x === Math.<span class="me1">floor</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span> ? x : <span class="br0">&#40;</span>x = Math.<span class="me1">floor</span><span class="br0">&#40;</span>x<span class="br0">&#41;</span><span class="br0">&#41;</span> + <span class="nu0">1</span>;</p>
	<p>&nbsp; &nbsp;<span class="kw1">return</span> s.<span class="me1">substr</span><span class="br0">&#40;</span><span class="nu0">0</span>, x<span class="br0">&#41;</span>.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">reverse</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">''</span><span class="br0">&#41;</span> === s.<span class="me1">substr</span><span class="br0">&#40;</span>y,len<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<p>The idea here is just split the string in half, reverse one of the two pieces and compare them.  For example:</p>
	<p>TOOT: splits into "TO" and "OT."  Reverse one of them, say the second part ("OT") and compare.</p>
	<p>If you've got a odd number of characters, you can ignore the middle most character:</p>
	<p>RACECAR: splits into "RAC" and "CAR" (ignore the "E" in the middle).  Reverse the second part ("CAR") and compare.</p>
	<p>As it turned out, this seemed to be faster than the other two methods.  Not by orders of magnitude, but not insignificantly either.  Here are the number from Firefox, running each function 10,000 time on the string "gohangasalamiimalasagnahog" (go hang a salami, i'm a lasagna hog).</p>
	<ul>
	<li>(Traverse from both ends): 797ms</li>
	<li>(Split/Reverse/Join): 969ms</li>
	<li>(Compare halves): 640ms</li>
	</ul>
	<p>Of course, numbers varied slightly during each run, but overall the they were consistent relative to each other.</p>
	<p>So there ya go.  Nothing in particular I wanted to point out here; just found it interesting and thought you might too.</p>
	<p>Think my code sucks?  Got a better solution?  Say so in the comments (you won't hurt my feelings).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/06/14/palindromes/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>In Honor of Caspian (enhancing Gimme)</title>
		<link>http://blog.stchur.com/2008/05/16/in-honor-of-caspian-enhancing-gimme/</link>
		<comments>http://blog.stchur.com/2008/05/16/in-honor-of-caspian-enhancing-gimme/#comments</comments>
		<pubDate>Sat, 17 May 2008 03:47:53 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[CSS Related]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Gimme]]></category>
		<category><![CDATA[Useful Functions]]></category>
		<category><![CDATA[]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[John Resig]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Shaun Inman]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/05/16/in-honor-of-caspian-enhancing-gimme/</guid>
		<description><![CDATA[	The Chronicles of Narnia: Prince Caspian arrived in theaters today, and for those of you who haven't noticed, all of the Gimme codename releases are named after characters from the Chronicles of Narnia, since it is the greatest fantasy series ever written (sorry Lord of the Rings and Harry Potter fans, but I'm afraid that [...]]]></description>
			<content:encoded><![CDATA[	<p><a href = "http://en.wikipedia.org/wiki/Prince_Caspian" title = "Prince Caspian">The Chronicles of Narnia: Prince Caspian</a> arrived in theaters today, and for those of you who haven't noticed, all of the Gimme codename releases are named after characters from the <a href = "http://www.narniaweb.com" title = "Narnia Web">Chronicles of Narnia</a>, since it is the greatest fantasy series ever written (sorry Lord of the Rings and Harry Potter fans, but I'm afraid that yes, Narnia, <em>is</em> better).</p>
	<p>Anyway, since the current beta release of Gimme is "Caspian" I figured I'd do a post today in honor of Gimme and the movie (ok, it helps that I also have something worth writing about too).</p>
	<p>So anyway, on to what this post is really about: enhancing Gimme.</p>
	<p>Not too long ago, <a href = "http://www.shauninman.com" title = "Shaun Inman">Shaun Inman</a> wrote about his proposal for <a href = "http://shauninman.com/archive/2008/05/05/css_qualified_selectors" title = "CSS Qualified Selectors">CSS Qualified Selectors</a>.</p>
	<p>It's a good idea; I've actually had the same idea and thought briefly about making it part of Gimme's core CSS selector engine.  Only, in my model, I have the left-hand-side and the right-hand-side of the <code><</code> symbol switched.  It feels more natural to me that way, because in most CSS selector rules, you can simply look to the far right of the selector rule and know what type of "thing" you're going to be selecting.</p>
	<p>Thus, I feel that this:</p>
	<div class="dean_ch" style="white-space: nowrap;">img &lt; a&nbsp; &nbsp; &nbsp;<span class="coMULTI">/* select all &lt;a&gt; elements that contain an &lt;img&gt; element */</span></div>
	<p>feels more natural than this:</p>
	<div class="dean_ch" style="white-space: nowrap;">a &lt; img&nbsp; &nbsp; &nbsp;<span class="coMULTI">/* same logic as above -- Shaun's approach */</span></div>
	<p>But this is just details; the idea is the same either way.</p>
	<p>So anyway, after Shaun published his idea, <a href = "http://www.ejohn.com" title = "John Resig">John Resig</a> chimed in and mentioned that <a href = "http://www.jquery.com" title = "jQuery">jQuery</a> supports this already via <a href = "http://ejohn.org/blog/qualified-selectors-in-jquery/" title = "jQuery :has(..)">pseudo :has(..)</a>.</p>
	<p>Well that's pretty cool, but since <a href = "http://codeplex.com/gimme" title = "The Gimme Javascript Library">Gimme</a> is my library, naturally, I feel compelled to make sure it stacks up against the competition, so I thought to myself: "self, can Gimme do this?" to which a mental reply came back "No, remember? You decided no to implement it."</p>
	<p>And I would have just left it at that, because after all, I decided not to implement it for a reason (and I figured that's where I <em>would</em> leave it).</p>
	<p>But then, today, my officemate surprised me by asking "Hey, I have a question about Gimme.  I'm working with a page where I need to select a &lt;table&gt; element that has an &lt;h1&gt;.  Can Gimme do this?"</p>
	<p>Well crap!  What are the odds that this would come up again so quickly?</p>
	<p>Not being one to disappoint, I said "You know what? I decided not to implement it, but I did put significant effort into making Gimme's selector engine extensible.  I bet we can write an extension really easily."</p>
	<p>So a few minutes later, we came up with this little gem:</p>
	<div class="dean_ch" style="white-space: nowrap;">Gimme.<span class="me1">Selectors</span>.<span class="me1">addPseudo</span><span class="br0">&#40;</span><span class="st0">'has'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>_elem, _pseudo<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">var</span> children = Gimme.<span class="me1">query</span><span class="br0">&#40;</span>_pseudo.<span class="me1">param</span>, _elem<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">return</span> children.<span class="me1">length</span> &gt; <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
	<p>Which means you can now use Gimme to do something like:</p>
	<div class="dean_ch" style="white-space: nowrap;">g<span class="br0">&#40;</span><span class="st0">'p:has(img.funny)'</span><span class="br0">&#41;</span>;&nbsp; <span class="co1">// select all &lt;p&gt;s that contain &lt;img&gt;s with class &quot;funny&quot;</span></div>
	<p>Unlike what John did, I didn't bother to map this back to the <code><</code> symbol.  I thought about it, and you could do it easily enough, but the more I think about it, the more I like how <code>:has(..)</code> reads.</p>
	<p>It's not likely that I'll make something like this part of the core Gimme library unless it start popping up everywhere.  It comes up occasionally, but not enough to warrant making it part of the core (at least, not enough in my personal experiences so far anyway).</p>
	<p>So there ya go!  Think of this as edition 1 of "Gimme can do that too" with (hopefully) many more editions to come.</p>
	<p>Comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/05/16/in-honor-of-caspian-enhancing-gimme/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programmatically Accessing the CSS Rules in Your Page&#039;s Stylesheets</title>
		<link>http://blog.stchur.com/2008/04/09/programmatically-accessing-the-css-rules-in-your-pages-stylesheets/</link>
		<comments>http://blog.stchur.com/2008/04/09/programmatically-accessing-the-css-rules-in-your-pages-stylesheets/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 19:10:55 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[Useful Functions]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/04/09/programmatically-accessing-the-css-rules-in-your-pages-stylesheets/</guid>
		<description><![CDATA[	It's not a scenario that comes up too often, but every once in a while, I find the need to programmatically access a CSS rule in one of my stylesheets (which includes rules embedded in the page via the &#60;style&#62; tag).
	The major problem here is that there is only one mechanism available for accessing a [...]]]></description>
			<content:encoded><![CDATA[	<p>It's not a scenario that comes up too often, but every once in a while, I find the need to programmatically access a CSS rule in one of my stylesheets (which includes rules embedded in the page via the <code>&lt;style&gt;</code> tag).</p>
	<p>The major problem here is that there is only one mechanism available for accessing a <code>CSSStyleSheetDeclaration</code> object and its corresponding <code>CSSRule</code> collection.</p>
	<p>And that (rather unfortunate) mechanism is by zero-based index, which means you need to know exactly where in the DOM a particular stylesheet lives and exactly where in said stylesheet the particular rule you're interested in lives.</p>
	<p>Needless to say, accessing these sheets and rules by index is risky, since any update to your CSS may require an update to the code which accesses your CSSRule by index.</p>
	<p>You might be thinking that one solution is to put the rule (or rules) that interest you in a predictable place (e.g. the very first rule of the very first stylesheet in your page), but even this is risky and error prone (I know; I did it, and it once came back to bite me).</p>
	<p>In light of these issues, I wrote a function that, given a CSS selector rule, finds the the corresponding CSSRule (if it exists).  Since this is not necessarily a cheap process, the results are cached so that future requests for the same rule are returned in constant time.</p>
	<p>The full code is offered below, with explanations of anything interested embedded in comments.</p>
	<h3>The findCSSRule(..) function</h3>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> findCSSRule = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span> &nbsp; <br />
&nbsp; &nbsp;<span class="kw2">var</span> cache = <span class="br0">&#123;</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp;<span class="kw2">function</span> worker<span class="br0">&#40;</span>_selector, _media<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> cache<span class="br0">&#91;</span>_selector<span class="br0">&#93;</span> !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> cache<span class="br0">&#91;</span>_selector<span class="br0">&#93;</span>;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// return the cached rule if it exists</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;_media = _media || <span class="st0">''</span>;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <span class="co1">// if _media isn't passed in, default to empty string</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> i, j,<br />
&nbsp; &nbsp;&nbsp; &nbsp;mediaText,<br />
&nbsp; &nbsp;&nbsp; &nbsp;sheet, rule, rules, rulesLen,<br />
&nbsp; &nbsp;&nbsp; &nbsp;sheets = document.<span class="me1">styleSheets</span>,<br />
&nbsp; &nbsp;&nbsp; &nbsp;sheetsLen = sheets.<span class="me1">length</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">for</span> <span class="br0">&#40;</span>i = <span class="nu0">0</span>; i &lt; sheetsLen; i++<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;sheet = sheets<span class="br0">&#91;</span>i<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// accessing the media attribute of the stylesheet requires a bit of cross-browser trickery</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;mediaText = <span class="kw1">typeof</span> sheet.<span class="me1">media</span>.<span class="me1">mediaText</span> !== <span class="st0">'undefined'</span> ? sheet.<span class="me1">media</span>.<span class="me1">mediaText</span> : sheet.<span class="me1">media</span>;<br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// don't waste time with this sheet if its not of the right media type</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>mediaText.<span class="me1">indexOf</span><span class="br0">&#40;</span>_media<span class="br0">&#41;</span> === <span class="nu0">-1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">continue</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;rules = sheet<span class="br0">&#91;</span>prop<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;rulesLen = rules.<span class="me1">length</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">for</span> <span class="br0">&#40;</span>j = <span class="nu0">0</span>; j &lt; rulesLen; j++<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;rule = rules<span class="br0">&#91;</span>j<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>rule.<span class="me1">selectorText</span> === _selector<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> cache<span class="br0">&#91;</span>_selector<span class="br0">&#93;</span> = rule;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="kw2">null</span>; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="co1">// this function is returned if the browser doesn't provide a known</span><br />
&nbsp; &nbsp;<span class="co1">// mechanism for accessing stylesheets and/or CSS rules</span><br />
&nbsp; &nbsp;<span class="kw2">function</span> unsupported<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="kw2">null</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="co1">// make sure there's at least 1 stylesheet to search,</span><br />
&nbsp; &nbsp;<span class="co1">// then prop will be &quot;cssRules&quot; (W3C), &quot;rules&quot; (IE), or null (unsupported)</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> test = document.<span class="me1">styleSheets</span>.<span class="me1">length</span> &gt; <span class="nu0">0</span> &amp;&amp; document.<span class="me1">styleSheets</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;<span class="kw2">var</span> prop = test &amp;&amp;<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#40;</span><span class="kw1">typeof</span> test.<span class="me1">cssRules</span> !== <span class="st0">'undefined'</span> ? <span class="st0">'cssRules'</span> :<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">typeof</span> test.<span class="me1">rules</span> !== <span class="st0">'undefined'</span> ? <span class="st0">'rules'</span> :<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">null</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;<span class="co1">// false prop (meaning no stylesheets or unsupported method of accessing the CSSRules),</span><br />
&nbsp; &nbsp;<span class="co1">// means this function won't work, so rather than return the worker, return the unsupported function</span><br />
&nbsp; &nbsp;<span class="kw1">return</span> prop ? worker : unsupported;<br />
<span class="br0">&#125;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
	<h3>Caveats:</h3>
	<p>This function isn't perfect by any means -- a few things need to be called out.</p>
	<ol>
	<li>Specifying media type could be more flexible:  I'm just doing a simple <code>indexOf(..)</code> check on the stylesheet's media attribute, which means that if you want to filter by more than one media type, you'll need to specify the comma separated list yourself, and you'll need to make sure you do it in the right order if you want the <code>indexOf(..)</code> check to pass.  A more robust solution might be to parse a comma separated string of media types for the user, or to allow the user to specify multiple media types in an array.</li>
	<li>Memory consumption could be an issue:  I don't think it's likely, but if you're grabbing lots and lots of rules, the cache could become large and memory leaks could become an issue (since the cache is created in a closure).  I'm not overly concerned about this though -- you can decide for yourself is this is a big deal.</li>
	<li>No mechanism for handling dynamically created styles:  If you happen to load a stylesheet later in page's lifetime (after the initial load) this function is still going to return the <code>unsupported()</code> function, since it does its check once, up front, to decide whether or not accessing stylesheets/rules is feasible.  I'm okay with this, but again, you can decide for yourself.</li>
	</ul>
	<h3>Examples:</h3>
	<p>Now that the function is written, a few examples are in order.  Assume the following stylesheets:</p>
	<h4> - stylesheet 0 - (media = "print") </h4>
	<div class="dean_ch" style="white-space: nowrap;">div&gt;span<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">border</span>: <span class="re3">10px</span> <span class="kw2">solid</span> <span class="kw2">red</span>;<br />
<span class="br0">&#125;</span></p>
	<p><span class="re1">.christmas</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">background</span>: <span class="kw2">green</span>;<br />
&nbsp; &nbsp;<span class="kw1">color</span>: <span class="kw2">red</span>;<br />
<span class="br0">&#125;</span></p>
	<p><span class="re1">.pascha</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">background</span>: <span class="kw2">purple</span>;<br />
&nbsp; &nbsp;<span class="kw1">color</span>: <span class="kw2">yellow</span>;<br />
<span class="br0">&#125;</span></div>
	<h4> - stylesheet 1 - (media = "screen")</h4>
	<div class="dean_ch" style="white-space: nowrap;">div&gt;span<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">border</span>: <span class="re3">5px</span> <span class="kw2">dotted</span> <span class="kw1">blue</span>;<br />
<span class="br0">&#125;</span></p>
	<p><span class="re0">#main</span> div~span<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">background</span>: pink;<br />
<span class="br0">&#125;</span></div>
	<p>Accessing any of the above styles is fairly trivial.</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="co1">// returns the div&gt;span rule from stylesheet 0</span><br />
<span class="kw2">var</span> r1 = findCSSRule<span class="br0">&#40;</span><span class="st0">'div&gt;span'</span>, <span class="st0">'print'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<br />
<span class="co1">// also returns the div&gt;span rule from stylesheet 0 (since media default to empty string, the first stylesheet with this rule will match)</span><br />
<span class="kw2">var</span> r2 = findCSSRule<span class="br0">&#40;</span><span class="st0">'div&gt;span'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<br />
<span class="co1">// returns the div&gt;span rule from stylesheet 1</span><br />
<span class="kw2">var</span> r3 = findCSSRule<span class="br0">&#40;</span><span class="st0">'div&gt;span'</span>, <span class="st0">'scren'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<br />
<span class="co1">// returns the .pascha rule from stylesheet 0</span><br />
<span class="kw2">var</span> r4 = findCSSRule<span class="br0">&#40;</span><span class="st0">'.pascha'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<br />
<span class="co1">// returns null</span><br />
<span class="kw2">var</span> r5 = findCSSRule<span class="br0">&#40;</span><span class="st0">'.halloween'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<br />
<span class="co1">// returns the #main div~span rule from stylesheet 1</span><br />
<span class="kw2">var</span> r6 = findCSSRule<span class="br0">&#40;</span><span class="st0">'#main div~span'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<br />
<span class="co1">// returns null (b/c the rule doesn't exist in a stylesheet with media = &quot;print&quot;</span><br />
<span class="kw2">var</span> r7 = findCSSRule<span class="br0">&#40;</span><span class="st0">'#main div~span'</span>, <span class="st0">'print'</span><span class="br0">&#41;</span>;</div>
	<p>And there you have it!</p>
	<p>Comments, questions, suggestions, complaints? Bring 'em on!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/04/09/programmatically-accessing-the-css-rules-in-your-pages-stylesheets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Accessing the Native DOMElement&#039;s prototype in Safari 2</title>
		<link>http://blog.stchur.com/2008/01/24/accessing-the-native-domelements-prototype-in-safari-2/</link>
		<comments>http://blog.stchur.com/2008/01/24/accessing-the-native-domelements-prototype-in-safari-2/#comments</comments>
		<pubDate>Thu, 24 Jan 2008 20:17:00 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Useful Functions]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/01/24/accessing-the-native-domelements-prototype-in-safari-2/</guid>
		<description><![CDATA[	UPDATE:
	It turns out, Safari has an interesting quirk.  Simply executing this Javascript:
	document.getElementsByTagName&#40;'html'&#41;&#91;0&#93;;
	is enough to make the "[[DOMElement.prototype]]" property come into existence.  This appears to be true regardless of how early in the page load cycle you execute the Javascript, so perhaps the whole polling script I suggest below is unnecessary after all.
	For the [...]]]></description>
			<content:encoded><![CDATA[	<div class = "note"><a id = "update">UPDATE:</a></p>
	<p>It turns out, Safari has an interesting quirk.  Simply executing this Javascript:</p>
	<div class="dean_ch" style="white-space: nowrap;">document.<span class="me1">getElementsByTagName</span><span class="br0">&#40;</span><span class="st0">'html'</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>;</div>
	<p>is enough to make the "[[DOMElement.prototype]]" property come into existence.  This appears to be true regardless of how early in the page load cycle you execute the Javascript, so perhaps the whole polling script I suggest below is unnecessary after all.</div>
	<p>For the longest time, I thought it was just completely impossible to access the prototype of the native <code>DOMElement</code> (or <code>HTMLElement</code> in most other browsers) in Safari 2.</p>
	<p>As an alternative, I'd see people extend the <code>Object</code> object's prototype in order to add functionality to DOM elements (heck, I've done this myself -- shame on me).  This is problematic for a couple of reasons:</p>
	<ol>
	<li>Programmers expect <code>var myObj = {}</code> to  be an empty object (i.e. it should have no properties).  Extending <code>Object</code>'s prototype breaks this.</li>
	<li>Iterating an object's properties via <code>for .. in</code> now requires the use of <code>.hasOwnProperty(..)</code> to ensure you're not accessing properties you don't intend to access.</li>
	</ol>
	<p>I searched high and low, and I experimented (numerous times) trying to find <em>some</em> way of accessing the native <code>DOMElement</code> in Safari 2, but always to no avail... until now.</p>
	<div class = "note">
It's worth noting that this is not an issue in Safari 3.  Extending DOM elements in that browser is easy:</p>
	<div class="dean_ch" style="white-space: nowrap;">HTMLElement.<span class="me1">prototype</span>.<span class="me1">foo</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'foo'</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;<br />
<span class="co1">// assume elem is a reference to some valid DOM element</span><br />
elem.<span class="me1">foo</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// alerts &quot;foo&quot;</span></div>
	</div>
	<h3>At long last, a solution for Safari 2</h3>
	<p>Credit totally goes to my co-worker, Derrick Quan, as he is the one who discovered the initial solution.</p>
	<p>It turns out there there is a property on the <code>window</code> object in Safari 2 which is identified by the string <code>"[[DOMElement.prototype]]"</code> (case sensitive and double brackets on both sides required).</p>
	<p>Now you can't access this directly because <code>[[DOMElement.prototype]]</code> is not a valid variable name.  It doesn't have to be though, since it lives as a property of some other object (the <code>window</code> object in this case).</p>
	<p>This means that we can access "[[DOMElement.prototype]]" by treating it like what it is (a property on the <code>window</code> object).</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> DOMElemProto = window<span class="br0">&#91;</span><span class="st0">'[[DOMElement.prototype]]'</span><span class="br0">&#93;</span>;<br />
DOMElemProto.<span class="me1">foo</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'foo'</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;<br />
<span class="co1">// assume elem is a reference to a valid DOM element</span><br />
elem.<span class="me1">foo</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// alerts &quot;foo&quot;</span></div>
	<p><del>There is "gotcha" however</del> (maybe not -- see the <a href = "#update">UPDATE note</a> at the beginning of this post).</p>
	<p>It seems that the <code>[[DOMElement.prototype]]</code> property is not available until the DOM is fully loaded, which means if you want to be confident in accessing the property, you'll need to do it, either in a window "load" listener, or by using a DOMContentLoaded-type script (see Hedger Wang's post: <a href = "http://www.hedgerwow.com/360/dhtml/ie-dom-ondocumentready.html" title = "An alternative for DOMContentLoaded on Internet Explorer">An alternative for DOMContentLoaded on Internet Explorer</a> and/or Stuart Langridge's: <a href = "http://www.kryogenix.org/days/2007/09/26/shortloaded" title = "DOMContentLoaded for IE, Safari, everything, without document.write">DOMContentLoaded for IE, Safari, everything, without document.write</a>).</p>
	<p>Alternatively, you could poll for the existence of the <code>[[DOMElement.prototype]]</code> property, and take action once it finally "comes alive."</p>
	<pSomething like this could work:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> getDOMElemProto<span class="br0">&#40;</span>_retries<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">this</span>.<span class="me1">retries</span> = <span class="kw1">this</span>.<span class="me1">retries</span> || _retries;<br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw1">this</span>.<span class="me1">count</span> = <span class="br0">&#40;</span><span class="kw1">this</span>.<span class="me1">count</span> || <span class="nu0">0</span><span class="br0">&#41;</span> + <span class="nu0">1</span><span class="br0">&#41;</span> &gt; _retries<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// abort</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="kw2">var</span> DOMElemProto = window<span class="br0">&#91;</span><span class="st0">'[[DOMElement.prototype]]'</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> DOMElemProto === <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;setTimeout<span class="br0">&#40;</span>getDOMElemProto, <span class="nu0">100</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;extendDOMElements<span class="br0">&#40;</span>DOMElemProto<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
	<p><span class="kw2">function</span> extendDOMElements<span class="br0">&#40;</span>_proto<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// Extend the DOMElement.prototype as necessary here</span><br />
&nbsp; &nbsp;_proto.<span class="me1">foo</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'foo'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span>;</p>
	<p>&nbsp; &nbsp;_proto.<span class="me1">bar</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'bar'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
getDOMProto<span class="br0">&#40;</span><span class="nu0">50</span><span class="br0">&#41;</span>;</div>
	<p>After a few retries, Safari2 should be able to access <code>[[DOMElement.prototype]]</code>, while other browsers will give up after 50 tries.</p>
	<p>Now I haven't done <em>extensive</em> testing on this, but initial tests seem to indicate that this works quite well.  And it <em>doesn't</em> resort to extending the <code>Object</code> object's prototype at all, so users of this script should not have to worry about object literals containing unexpected properties.</p>
	<p>I think this is pretty cool.</p>
	<p>Comments, questions, suggestions, complaints... all welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/01/24/accessing-the-native-domelements-prototype-in-safari-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>setCapture with Gimme</title>
		<link>http://blog.stchur.com/2007/11/21/setcapture-with-gimme/</link>
		<comments>http://blog.stchur.com/2007/11/21/setcapture-with-gimme/#comments</comments>
		<pubDate>Thu, 22 Nov 2007 04:44:01 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Gimme]]></category>
		<category><![CDATA[Useful Functions]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/11/21/setcapture-with-gimme/</guid>
		<description><![CDATA[	In my last blog post I talked about how to re-route events in Javascript.  It comes in handy from time to time, but some people prefer an alternate paradigm -- one that is probably more familiar to Win32 programmers.
	It's called setCapture.  It's proprietary, and it's native to only the IE browser (as far [...]]]></description>
			<content:encoded><![CDATA[	<p>In my <a href = "http://blog.stchur.com/2007/11/16/re-routing-events-in-javscript/" title = "Re-routing Events in Javascript">last blog post</a> I talked about how to re-route events in Javascript.  It comes in handy from time to time, but some people prefer an alternate paradigm -- one that is probably more familiar to Win32 programmers.</p>
	<p>It's called <code>setCapture</code>.  It's proprietary, and it's native to only the IE browser (as far as I know).</p>
	<h3>What's .setCapture() good for?</h3>
	<p>Put simply, <code>.setCapture()</code> redirects all <i>mouse</i> events to a specified DOM element until a call to <code>.releaseCapture()</code> is made.  Why would you want this?  I can think of a couple scenarios.</p>
	<ol>
	<li>Drag n' Drop: you wire up mousedown to some element to start the drag operation, but wiring up mousemove and mouseup on that same element could be problematic -- the user may mouse too fast and your code might not be able to "keep up."  Using <code>.setCapture()</code> on said element however, will redirect all mouse events to the appropriate element so that the mousemove and mouseup handlers are guaranteed to execute.</li>
	<li>Dropdown Menus: you want the next mousedown to dismiss a dropdown menu.  A first crack at this might be to wire up mousedown to the <code>&lt;body&gt;</code> element, but if some other element on the page is listening for mousedown and is stopping event propagation, the mousedown may never make it to the <code>&lt;body&gt;</code> element -- <code>.setCapture()</code> will solve this problem.</li>
	</li>
	</ol>
	<p>These aren't the only applications of <code>.setCapture()</code> of course, but they're two of the most common and they're a good illustration of how <code>.setCapture()</code> can be useful.</p>
	<h3>Gimme's version of .setCapture(..)</h3>
	<p>Even though Mozilla/Firefox and other W3C browsers don't natively support <code>.setCapture()</code>, <a href = "http://codeplex.com/gimme" title = "The Gimme Javascript Library">Gimme</a> solves this problem by simulating the capability for browsers  that don't natively support it.  Using Gimme's version is a snap.</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="co1">// just a shortcut for document.getElementById(..)</span><br />
<span class="kw2">var</span> dragElem = Gimme.<span class="me1">id</span><span class="br0">&#40;</span><span class="st0">'dragElem'</span><span class="br0">&#41;</span>;</p>
	<p><span class="co1">// #dragElem will capture all mouse events until</span><br />
<span class="co1">// a call to Gimme.Events.releaseMouse() is made</span><br />
Gimme.<span class="me1">Events</span>.<span class="me1">captureMouse</span><span class="br0">&#40;</span>dragElem<span class="br0">&#41;</span>;</div>
	<p>A simple call to <code>Gimme.Events.captureMouse(myElem)</code> will do the trick (where <code>myElem</code> is the DOM element that should capture all mouse events).</p>
	<p>This example, of course, doesn't accomplish anything very useful, but here's an example that's a bit more practical.</p>
	<p>This snippet gives drag/drop capabilities to all elements marked with the class "draggable" (it looks long but that's just comments and a big font).</p>
	<div class="dean_ch" style="white-space: nowrap;">g<span class="br0">&#40;</span><span class="st0">'.draggable'</span><span class="br0">&#41;</span>.<span class="me1">iterate</span><span class="br0">&#40;</span>makeDraggable<span class="br0">&#41;</span>;<br />
<span class="kw2">function</span> makeDraggable<span class="br0">&#40;</span>idx<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// variables to keep track of the drag element's start position</span><br />
&nbsp; &nbsp;<span class="co1">// and the initial mousedown position</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> elemStartPos, mouseStartPos;</p>
	<p>&nbsp; &nbsp;<span class="co1">// wire up mousedown to start the drag operation</span><br />
&nbsp; &nbsp;<span class="co1">// and stop click events from propagating (just in case)</span><br />
&nbsp; &nbsp;<span class="kw1">this</span><br />
&nbsp; &nbsp;.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="st0">'mousedown'</span>, mouseDown<span class="br0">&#41;</span><br />
&nbsp; &nbsp;.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="st0">'click'</span>, stopEvent<span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;<span class="kw2">function</span> mouseDown<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// instruct all mouse events to be redirected to the current dragElem</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;Gimme.<span class="me1">Events</span>.<span class="me1">captureMouse</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// prevent the mousedown event from propagating</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">stopPropagation</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// create a gimme object from the element being moused down on</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> gObj = g<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// keep a ref to the dragElem's start position</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// and to the initial mousedown position</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;elemStartPos = gObj.<span class="me1">getPagePosition</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;mouseStartPos = Gimme.<span class="me1">Screen</span>.<span class="me1">getMousePosition</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// now, hook the mousemove and mouseup events</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;gObj<br />
&nbsp; &nbsp;&nbsp; &nbsp;.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="st0">'mousemove'</span>, mouseMove<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="st0">'mouseup'</span>, mouseUp<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="kw2">function</span> mouseMove<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// prevent the mousemove event from propagating</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">stopPropagation</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// get the current mouse position</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> mousePos = Gimme.<span class="me1">Screen</span>.<span class="me1">getMousePosition</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// position the dragElem (element's start position + mouse delta)</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;g<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;.<span class="me1">setStyle</span><span class="br0">&#40;</span><span class="st0">'top'</span>, elemStartPos.<span class="me1">y</span> + <span class="br0">&#40;</span>mousePos.<span class="me1">y</span> - mouseStartPos.<span class="me1">y</span><span class="br0">&#41;</span> + <span class="st0">'px'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;.<span class="me1">setStyle</span><span class="br0">&#40;</span><span class="st0">'left'</span>, elemStartPos.<span class="me1">x</span> + <span class="br0">&#40;</span>mousePos.<span class="me1">x</span> - mouseStartPos.<span class="me1">x</span><span class="br0">&#41;</span> + <span class="st0">'px'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="kw2">function</span> mouseUp<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// instruct Gimme to stop capturing mouse events</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;Gimme.<span class="me1">Events</span>.<span class="me1">releaseMouse</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// prevent the mouseup event from propagating</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">stopPropagation</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// remove the mousemove and mouseup handlers</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;g<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;.<span class="me1">removeEvent</span><span class="br0">&#40;</span><span class="st0">'mousemove'</span>, mouseMove<span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;.<span class="me1">removeEvent</span><span class="br0">&#40;</span><span class="st0">'mouseup'</span>, mouseUp<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="kw2">function</span> stopEvent<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">stopPropagation</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">preventDefault</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
	<p>Before I get into an explanation of the code, the following note is significant:</p>
	<div class = "note">
The current version of Gimme (<a href = "http://www.codeplex.com/gimme/Release/ProjectReleases.aspx?ReleaseId=7638" title = "Gimme (Belisar)">Belisar</a>) doesn't offer <code>Gimme.Events.captureMouse(..)</code>.  This capability is new to Gimme (Caspian) which is currently in a pre-release state.  You can access Caspian now by visiting the <a href = "http://www.codeplex.com/gimme/SourceControl/ListDownloadableCommits.aspx" title = "Gimme Source">Source Code Section</a> on the Gimme Codeplex site, or you can wait for the official release of Caspian, which should be sometime in late January.
</div>
	<h3>Explanation</h3>
	<p>If you understand Gimme, the code here is really pretty straight-forward.</p>
	<p> A mousedown event starts the drag operation by recording the mouse down position and the element's start position.  Then, the <code>mouseMove</code> handler ensures that the element moves along with the mouse delta (delta from the mouse start position).  Finally, the <code>mouseUp</code> handler ends the drag operation by removing event handlers that are no longer needed and releasing capture.</p>
	<p>We prevent events from propagating (bubbling) in all cases, so that we don't get other elements interfering during a drag operation.  And we use Gimme's <code>Gimme.Events.captureMouse(..)</code> capabilities to ensure the the mousemove and mouseup events are directed to the appropriate element.  Otherwise we risk some other element "stealing" the mousemove or mouseup away from the intended element.</p>
	<h3>What does <code>this</code> refer to exactly?</h3>
	<p>Good question; it's the one thing in the Gimme drag/drop code that I can see tripping people up.  The <code>this</code> keyword is somewhat polymorphic in Gimme, so what does it refer to exactly?</p>
	<p>The answer is that is depends on context.  Most of the time in Gimme, you'll be using <code>this</code> inside of an event handler function.  In that case, <code>this</code> refers to the <i>DOM</i> element to which the event was wired up.  For example:</p>
	<div class="dean_ch" style="white-space: nowrap;">g<span class="br0">&#40;</span><span class="st0">'#myElem'</span><span class="br0">&#41;</span>.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="st0">'click'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// alerts &quot;myElem&quot;</span><br />
&nbsp;&nbsp; <span class="co1">// since 'this' refers to #myElem in the current context</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span><span class="kw1">this</span>.<span class="me1">id</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
	<p>In some cases though, you may want to use the Gimme <a href = "http://www.codeplex.com/gimme/Wiki/View.aspx?title=.iterate%28callback%29&#038;referringTitle=Complete%20API%20Reference" title = "The Gimme .iterate(..) function">.iterate(..)</a> function.  In that case, <code>this</code> refers to the current Gimme Object being iterated over, <i>not</i> a DOM element, but it's possible to combine both concepts.  For instance:</p>
	<div class="dean_ch" style="white-space: nowrap;">g<span class="br0">&#40;</span><span class="st0">'#container &gt; .funny'</span><span class="br0">&#41;</span>.<span class="me1">iterate</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span>idx<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// here, 'this' refers to the current Gimme Object,</span><br />
&nbsp; &nbsp;<span class="co1">// which is why .addEvent(..) is okay here</span><br />
&nbsp; &nbsp;<span class="kw1">this</span>.<span class="me1">addEvent</span><span class="br0">&#40;</span><span class="st0">'click'</span>, <span class="kw2">function</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// here, 'this' refers to the DOM element receiving the click event,</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// so we can access native properties, like .parentNode</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">this</span>.<span class="me1">parentNode</span>.<span class="me1">removeChild</span><span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
	<p>In case you hadn't figured it out, the above snippet makes it so that all elements with the class "funny" that are direct children of <code>#container</code> will be removed from the DOM when clicked -- pretty trivial with Gimme.</p>
	<p>But this is all secondary to the discussion at hand: capturing mouse events, which, thanks to Gimme, is also pretty trivial!</p>
	<p>If you're new to Gimme, check out the <a href = "http://gimme.stchur.com" title = "The Gimme Javascript Library">Gimme Promo Page</a> and the <a href = "http://codeplex.com/gimme">Gimme Codeplex Page</a>.</p>
	<p>You can also download a debug version of Caspian <a href = "http://gimme.stchur.com/src/debug/gimme.caspian.js" title = "Gimme (Caspian) Source">here</a> if you just want to monkey around with it.</p>
	<p>Note once again, that an official (and compressed) version of Caspian will be available sometime in late January.</p>
	<p>Comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/11/21/setcapture-with-gimme/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing Gimme</title>
		<link>http://blog.stchur.com/2007/06/22/introducing-gimme/</link>
		<comments>http://blog.stchur.com/2007/06/22/introducing-gimme/#comments</comments>
		<pubDate>Fri, 22 Jun 2007 17:08:16 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Beating IE into submission]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Useful Functions]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/06/22/introducing-gimme/</guid>
		<description><![CDATA[	It's been quite a while since I've blogged anything significant regarding Javascript.  This is largely due to the fact that I've been spending a good bit of my free time working on an open source project I started, called Gimme.
	Gimme is a Javascript Library designed to make performing common tasks, not only easier, but [...]]]></description>
			<content:encoded><![CDATA[	<p>It's been quite a while since I've blogged anything significant regarding Javascript.  This is largely due to the fact that I've been spending a good bit of my free time working on an open source project I started, called Gimme.</p>
	<p>Gimme is a Javascript Library designed to make performing common tasks, not only easier, but down-right trivial.</p>
	<h3>What does Gimme look like?</h3>
	<p>Gimme is remarkably easy to use and was purposely designed to be very readable.  Take the following snippet.</p>
	<div class="dean_ch" style="white-space: nowrap;">
g<span class="br0">&#40;</span><span class="st0">'.moveable'</span><span class="br0">&#41;</span>.<span class="me1">addClass</span><span class="br0">&#40;</span><span class="st0">'hasBeenMoved'</span><span class="br0">&#41;</span>.<span class="me1">slideToPoint</span><span class="br0">&#40;</span><span class="br0">&#123;</span>x: <span class="nu0">0</span>, y: <span class="nu0">0</span><span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
	<p>This code snippet grabs all elements on the page that have the class "moveable", adds to them, the class "hasBeenMoved," and then slides the elements (in a nice accelerated fashion) to the point (0, 0) on the page.  Pretty easy right?</p>
	<p>Believe it not, most tasks in Gimme are this easy (or easier).</p>
	<h3>Get started with Gimme</h3>
	<ul>
	<li>See it in action on the <a href = "http://gimme.stchur.com/demopage.html">Gimme Demo Page</a></li>
	<li>Learn what it can do at the <a href = "http://www.codeplex.com/gimme/Wiki/View.aspx?title=Complete%20API%20Reference&#038;referringTitle=Home">Gimme API Reference Page</a>.</li>
	<li>Download the source on the <a href = "http://www.codeplex.com/gimme/Release/ProjectReleases.aspx">Gimme Releases Page</a>.</li>
	</ul>
	<h3>Your Feedback</h3>
	<p>Gimme is still very young, but I'd love to get your feedback.  Please don't hesitate to try it out and <a href = "mailto:sstchur@yahoo.com">let me know what you think</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/06/22/introducing-gimme/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Serializing Objects in Javascript</title>
		<link>http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/</link>
		<comments>http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/#comments</comments>
		<pubDate>Fri, 06 Apr 2007 06:12:06 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Beating IE into submission]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Mozilla-specific]]></category>
		<category><![CDATA[Useful Functions]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/04/06/serializing-objects-in-javascript/</guid>
		<description><![CDATA[	Recently, in a personal project I'm working on, I came across a need to be able to represent any Javascript object as a string.  This isn't a problem since just about every object in Javascript can be represented with JSON (Javascript Object Notation).  Every modern browser can parse JSON for you easily enough [...]]]></description>
			<content:encoded><![CDATA[	<p>Recently, in a personal project I'm working on, I came across a need to be able to represent any Javascript object as a string.  This isn't a problem since just about every object in Javascript can be represented with <abbr title = "Javascript Object Notation">JSON</abbr> (Javascript Object Notation).  Every modern browser can parse <abbr>JSON</abbr> for you easily enough through <code>eval(..)</code>, and Gecko-based browsers even have the ability to reverse the process ("uneval" if you will) and give you back a string representation of an object through a call to <code>.toSource()</code>.</p>
	<p>If you need this ability in any other browser though, you're gonna have to write it yourself.  I needed this ability, so I wrote it (and posted it here for your enjoyment!)</p>
	<p><span id="more-41"></span></p>
	<h3>Gecko-based browsers, .toSource():</h3>
	<p>Gecko-based browsers provide a handy function: <code>.toSource()</code> that you can call on any object in your Javascript code to get back a JSON-like representation of that object.</p>
	<div class="dean_ch" style="white-space: nowrap;">
<span class="kw2">function</span> Cat<span class="br0">&#40;</span><span class="kw3">name</span>, age<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw1">this</span>.<span class="kw3">Name</span> = <span class="kw3">name</span>;<br />
&nbsp; &nbsp;<span class="kw1">this</span>.<span class="me1">Age</span> = age;<br />
&nbsp; &nbsp;<span class="kw1">this</span>.<span class="me1">Speak</span> = <span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw3">alert</span><span class="br0">&#40;</span><span class="st0">'Meow!'</span><span class="br0">&#41;</span>; <span class="br0">&#125;</span>;<br />
<span class="br0">&#125;</span></p>
	<p><span class="kw2">var</span> garfield = <span class="kw2">new</span> Cat<span class="br0">&#40;</span><span class="st0">'Garfield'</span>, <span class="nu0">5</span><span class="br0">&#41;</span>;<br />
<span class="kw3">alert</span><span class="br0">&#40;</span>garfield.<span class="me1">toSource</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
	<p><span class="coMULTI">/* garfield.toSource() yields:<br />
({Name:&quot;Garfield&quot;, Age:5, Speak:(function () {alert(&quot;Meow!&quot;);})})<br />
*/</span><br />
&nbsp;</div>
	<p>Pretty simple right?  You have an object; you want a string.  Just invoke the object's <code>.toSource()</code> function.</p>
	<h3>Serializing objects in other browsers:</h3>
	<p>Serializing an object manually (as is required by non Gecko-based browsers) requires a bit of <a href = "http://en.wikipedia.org/wiki/Recursion">recursion</a>.  Simple types like integers, booleans, and even functions are trivial to represent as strings.  Objects though, are more complicated because they can contain simple types <em>or</em> custom objects (which would need to be serialized themselves).  Those "inner" objects could in turn, contain <em>more</em> custom objects, which would <em>also</em> need to be serialized, and this pattern could (theoretically) go on forever.</p>
	<p>In practice of course, this pattern <em>will</em> (had better) come to an end.  And we can leverage that fact to write a recursive function that will return a string representation (in <abbr>JSON</sbbr> format) of a given object.</p>
	<h3>The serialize(..) function:</h3>
	<p>First the code, then the explanation.</p>
	<div class="dean_ch" style="white-space: nowrap;">
<span class="kw2">function</span> serialize<span class="br0">&#40;</span>_obj<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// Let Gecko browsers do this the easy way</span><br />
&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> _obj.<span class="me1">toSource</span> !== <span class="st0">'undefined'</span> &amp;&amp; <span class="kw1">typeof</span> _obj.<span class="me1">callee</span> === <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> _obj.<span class="me1">toSource</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span></p>
	<p>&nbsp; &nbsp;<span class="co1">// Other browsers must do it the hard way</span><br />
&nbsp; &nbsp;<span class="kw1">switch</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> _obj<span class="br0">&#41;</span><br />
&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// numbers, booleans, and functions are trivial:</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// just return the object itself since its default .toString()</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// gives us exactly what we want</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">case</span> <span class="st0">'number'</span>:<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">case</span> <span class="st0">'boolean'</span>:<br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">case</span> <span class="st0">'function'</span>:<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> _obj;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">break</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// for JSON format, strings need to be wrapped in quotes</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">case</span> <span class="st0">'string'</span>:<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="st0">'<span class="es0">\'</span>'</span> + _obj + <span class="st0">'<span class="es0">\'</span>'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">break</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">case</span> <span class="st0">'object'</span>:<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> str;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>_obj.<span class="me1">constructor</span> === Array || <span class="kw1">typeof</span> _obj.<span class="me1">callee</span> !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;str = <span class="st0">'['</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> i, len = _obj.<span class="me1">length</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">for</span> <span class="br0">&#40;</span>i = <span class="nu0">0</span>; i &lt; len<span class="nu0">-1</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span> str += serialize<span class="br0">&#40;</span>_obj<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> + <span class="st0">','</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;str += serialize<span class="br0">&#40;</span>_obj<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> + <span class="st0">']'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">else</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#123;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;str = <span class="st0">'{'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">var</span> key;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">for</span> <span class="br0">&#40;</span>key <span class="kw1">in</span> _obj<span class="br0">&#41;</span> <span class="br0">&#123;</span> str += key + <span class="st0">':'</span> + serialize<span class="br0">&#40;</span>_obj<span class="br0">&#91;</span>key<span class="br0">&#93;</span><span class="br0">&#41;</span> + <span class="st0">','</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;str = str.<span class="me1">replace</span><span class="br0">&#40;</span><span class="re0">/\,$/</span>, <span class="st0">''</span><span class="br0">&#41;</span> + <span class="st0">'}'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="br0">&#125;</span><br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> str;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">break</span>;</p>
	<p>&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw2">default</span>:<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">return</span> <span class="st0">'UNKNOWN'</span>;<br />
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<span class="kw1">break</span>;<br />
&nbsp; &nbsp;<span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></div>
	<p>Explaining a recursive function can be difficult, but I'll give it shot:</p>
	<p>The function accepts just one parameter: the object (<code>_obj</code>) to be serialized.  If you'll remember, I mentioned previously that simple types (string, boolean, number, etc...) were trivial because they all have an obvious string representation already.  Complex types though, are more difficult because they can be made up of additional complex types, which in turn could be made up of additional complex types (and so on).</p>
	<p>Of course, this pattern will eventually end; ultimately, everything is made up of simple types that have a string representation.  The trick is figuring out how to traverse through this maze of "types within types."  Recursion (simply stated: a function that calls itself) is perhaps the easiest way to solve this "types within types" problem.</p>
	<p>Recursive functions always have a termination case -- something which causes the function to <em>stop</em> calling itself.  Otherwise, the function would go into an infinite loop.  In our function, there are actually four different cases in which the <code>serialize(..)</code> doesn't need to call itself:</p>
	<ol>
	<li>typeof _obj is a number</li>
	<li>typeof _obj is a boolean</li>
	<li>typeof _obj is a function</li>
	<li>typeof _obj is a string</li>
	</ol>
	<p>If any of the above four conditions are met, returning a string representation is trivial, so we simply do it.</p>
	<div class = "note">
You'll notice that strings are treated separately from the other 3 types.  You'd think strings would be the most trivial case, but actually, there is one thing we must do before returning the "string representation" of <code>_obj</code> when it is of type string:  wrap it in quotes.  We need to do this, because JSON expects it, and if we ever want to be able to <code>eval(..)</code> the result of a <code>serialize(..)</code> call, we'll need these quotes.
</div>
	<p>The only other case to deal with is when <code>_obj</code> is of type <code>object</code>.  Within this case though, there are two "sub-cases" we need to deal with.  The first is when <code>_obj</code> is an <code>Array</code>, or when it has a <code>.callee</code> property (more on that later).  The second is well... anything else.</p>
	<h3>Basic Object Types</h3>
	<p>Your every-day, run-of-the-mill, object in Javascript can be represented as JSON with:</p>
	<p><code>{ key1: val1, key2: val2, ... }</code></p>
	<p>Where the keys are strings and the vals can be any simple type, or some custom object you've dreamed up.  The logic I've used is to simply loop through a given object's keys and build a string of comma delimited, <em>serialized</em> key/value pairs that are wrapped in { and }.</p>
	<p>Notice I said <em>serialized</em> key/value pairs.  Here, our function is calling itself as it builds the object representation.  This ensures that any objects within the object being serialized will <em>also</em> be serialized.  If we didn't do this, we'd end up with a lot of strings that looked (something) like this:</p>
	<p><code>{ key1: [object Object], key2: [object Object], etc... }</code></p>
	<p>And that's clearly not what we want.  We want those inner objects to be serialized as well, and that's what the recursive nature of our function will take care of for us.</p>
	<h3>Arrays</h3>
	<p>When <code>_obj</code> happens to be, not just any object, but more specifically, an <code>Array</code>, we have a better way of representing that as a string:</p>
	<p><code>[ val1, val2, val3, ... ]</code></p>
	<p>The logic I used here is to simply iterate through the array building a comma delimited list of <em>serialized</em> values, wrapped in [ and ].  Arrays in Javascript already have a <code>.toString()</code> function, but we can't use it here; if the Array contains objects, then the result of the Array 's <code>.toString()</code> could end up something like:</p>
	<p><code> [ [object Object], [object Object], etc... ]</code></p>
	<p>Again, not what we want, so we need to make sure we recursively serialize all of the elements in the array.</p>
	<h3>Arguments (the .callee "gotcha")</h3>
	<p>There's one bit of code I haven't discussed yet and it deals with the (possible) <code>.callee</code> property of the passed in <code>_obj</code>.  It turns out that <code>.toSource()</code> (native function used by Gecko-based browsers) doesn't do anything very useful when called on an <code>arguments</code> object.</p>
	<p>The <code>arguments</code> object is an array-like (but not an Array) object that is automatically available within the scope of every function.  Unfortunately, no matter what is contained within that <code>arguments</code> object, calling <code>.toSource()</code> on it will always return <code>"({})"</code></p>
	<p>In order to be able to serialize an <code>arguments</code> object then, we need some way to detect it and then treat it like an array.  The <code>.callee</code> property is a good choice because <code>arguments</code> objects have it, but other objects (to the best of my knowledge) do not.</p>
	<p>In the case of the <code>serialize(..)</code> function, I decided to use the native <code>.toSource()</code> function whenever it was available, <em>unless</em> the object were an <code>arguments</code> object, in which case, I send Gecko-based browsers down the same path as all other browsers for serialization.</p>
	<p>Finally, just for good measure, I've added a default case which returns the string <code>UNKNOWN</code> to handle a situation where no other cases applied.  Of course, we probably don't <em>want</em> <code> UNKNOWN</code> showing up in the our serialized strings, but it probably won't do much (immediate) harm if it ever does show up, <em>and</em> its presence would be a helpful indicator that there is some case not being met (that probably needs to be).</p>
	<h3>Conclusion:</h3>
	<p>What would you ever use a function like this for?  Well, In my case, I wanted to use a Javascript object as the key for a hash, but if I tried to do that, Javascript would just represent all of my (different) objects as the same string: <code>[object Object]</code>, which wouldn't do me any good.  By serializing the object, I can then use that serialized representation as a key in the hash.</p>
	<p>It's worked well for my need so far, but I haven't tested it a great deal.  If you find any bugs or short-comings, please let me know.</p>
	<p>As always, comments are welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
	</channel>
</rss>
