<?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; Advanced Javascript</title>
	<atom:link href="http://blog.stchur.com/category/advanced-javascript/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>Fetch (a stand-alone CSS querying engine)</title>
		<link>http://blog.stchur.com/2009/03/06/fetch-a-stand-alone-css-querying-engine/</link>
		<comments>http://blog.stchur.com/2009/03/06/fetch-a-stand-alone-css-querying-engine/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 06:00:16 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[CSS Related]]></category>
		<category><![CDATA[Cross-Browser]]></category>
		<category><![CDATA[Fetch]]></category>
		<category><![CDATA[Gimme]]></category>
		<category><![CDATA[CSS Querying]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/?p=124</guid>
		<description><![CDATA[	I've started work on a new side-project called Fetch.  It's a stand-alone CSS querying engine, designed to be super lightweight and offer high performance across all modern browsers.
	It's still very much in development and the source is a bit sloppy, but it currently weighs in at only 2.5k compressed and gzipped and (in Firefox3) [...]]]></description>
			<content:encoded><![CDATA[	<p>I've started work on a new side-project called Fetch.  It's a stand-alone CSS querying engine, designed to be super lightweight and offer high performance across all modern browsers.</p>
	<p>It's still very much in development and the source is a bit sloppy, but it currently weighs in at only 2.5k compressed and gzipped and (in Firefox3) either outperforms or is on par with all other major Javascript libraries out there*.</p>
	<p>It's definitely not ready for production use, but when it is, it will become the new CSS querying engine for Gimme and will also be available as a stand-alone library, which will be extensible (so you can add your own rules) and which will also be guaranteed to play nicely with other libraries by not adding to the prototype of any native objects and only introducing one single global variable (fetch).</p>
	<p>For anyone interested, the current (i.e. sloppy) source is available on CodePlex: <a href = "http://gimme.codeplex.com/SourceControl/changeset/view/32017#399762">fetch.js</a>.</p>
	<p>As I said, it's not ready for prime time and the code is sloppy (and probably buggy).  Consider yourself warned.</p>
	<p>* <small>Fetch was not compared with libraries that use XPath or querySelectorAll, because it uses neither, but rather is a pure Javascript implementation.  Upon release, it will take advantage of querySelectorAll where appropriate, but will not use XPath.</small>
</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2009/03/06/fetch-a-stand-alone-css-querying-engine/feed/</wfw:commentRss>
		<slash:comments>2</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>Firefox 3 .pageX / .pageY bug</title>
		<link>http://blog.stchur.com/2008/07/03/firefox-3-pagex-pagey-bug/</link>
		<comments>http://blog.stchur.com/2008/07/03/firefox-3-pagex-pagey-bug/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 17:40:49 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Firefox Related]]></category>
		<category><![CDATA[Mozilla-specific]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[dispatchEvent]]></category>
		<category><![CDATA[Firefox 3]]></category>
		<category><![CDATA[pageX]]></category>
		<category><![CDATA[pageY]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/07/03/firefox-3-pagex-pagey-bug/</guid>
		<description><![CDATA[	Firefox 3 has a bug.  It's somewhat obscure, and it probably doesn't affect you, but it did affect me.
	It also affected the Microsoft Virtual Earth MapControl, so if you use the VE MapControl for a mashup, your Firefox 3 users are going to be affected by this issue.
	The issue?  It has to do [...]]]></description>
			<content:encoded><![CDATA[	<p>Firefox 3 has a bug.  It's somewhat obscure, and it probably doesn't affect you, but it did affect me.</p>
	<p>It also affected the Microsoft <a href = "http://msdn.microsoft.com/en-us/virtualearth/default.aspx" title = "Microsoft Virtual Earth">Virtual Earth MapControl</a>, so if you use the VE MapControl for a mashup, your Firefox 3 users are going to be affected by this issue.</p>
	<p>The issue?  It has to do with a mouse event's <code>.pageX</code> and <code>.pageY</code> properties.  The values of those properties are supposed to report the "page" position of the mouse cursor, relative to the upper-left corner of the HTML page.  You can think of it as the absolute (x,y) of the mouse cursor.</p>
	<p>The nice thing about <code>.pageX/Y</code> is that serves as an easy way to get the mouse position, <em>regardless</em> of how much (or even if) the browser window is scrolled.</p>
	<p>Contrast <code>.pageX/Y</code> with <code>.clientX/Y</code>:  the latter reports (x,y) coordinates relative to the upper-left corner of the browser window, so these values <em>will</em> be affected by browser scroll position.</p>
	<p>Anyway, at this point, you're probably thinking that I'm going to tell you that Firefox 3 reports the wrong values for <code>.pageX/Y</code>, and that that's the bug.  It's not that simple though (again, I admit this is a somewhat obscure bug).</p>
	<p><em>Most</em> of the time, Firefox 3 reports the right values for <code>.pageX/Y</code>, but there is one case in which it doesn't.</p>
	<h3>Manually Dispatching Events in Javascript</h3>
	<p>A while back, I wrote a 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>.  In it, I explain how to create an event and initialize it with <code>myEvt.initMouseEvents(..)</code> (which takes a <a href = "http://developer.mozilla.org/en/docs/DOM:event.initMouseEvent" title = "Mozilla Developer Center (initMouseEvent)">boat-load</a> of parameters).</p>
	<p>Of all those parameters sent into <code>.initMouseEvents(..)</code>, 4 are of particular interest: <code>.screenX</code>, <code>.screenY</code>, <code>.clientX</code>, and <code>.clientY</code>.</p>
	<p>Notice that <code>.pageX</code> and <code>.pageY</code> are not in the list.  You don't get the ability to pass in <code>.pageX/Y</code> when manually creating/dispatching an event in Javascipt.  Presumably, the values for these properties are computed based on <code>.clientX/Y</code> and the browser's scroll position.</p>
	<p>So for example, if you initialize a MouseEvent with <code>.clientX</code> = 200 and <code>.clientY</code> = 300, and if the browser is scrolled 50 x 75, then your event's <code>.pageX</code> and <code>.pageY</code> values will be 250 and 375 respectively.</p>
	<p>Oops!  I mean, that's what the values <em>should</em> be.</p>
	<h3>The Bug</h3>
	<p>Firefox 2 actually gets it right, but Firefox 3 doesn't.</p>
	<p>When you're manually dispatching a MouseEvent in Firefox 3, the <code>.pageX/Y</code> property values will <em>always</em> be equal to the <code>.clientX/Y</code> values, <em>regardless</em> of browser scroll position.</p>
	<p>As I previously mentioned, this affects the VE MapControl, so it's easy to see the issue in action.  Just use Firefox 3 and point your browser to <a href = "http://maps.live.com" title = "Microsoft Live Search Maps">http://maps.live.com</a>.  Now make your browser window small enough to cause scroll bars to appear.  Scroll the browser window by some amount (doesn't matter how much) and try panning the map.  You should see the map "jump" during the initial pan.  The amount it "jumps" is going to be equal to the amount by which the browser window is scrolled.</p>
	<h3>The Fix</h3>
	<p>Microsoft has a work-around for this issue that is going to be released with the next version of Virtual Earth, but if you're a mashup dev using the VE MapControl, I've got a solution that you can use right now, and it goes like this:</p>
	<div class="dean_ch" style="white-space: nowrap;"><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> mouseEvt;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">typeof</span> document.<span class="me1">createEvent</span> !== <span class="st0">'undefined'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; mouseEvt = document.<span class="me1">createEvent</span><span class="br0">&#40;</span><span class="st0">'MouseEvents'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>mouseEvt &amp;&amp; mouseEvt.__proto__ &amp;&amp; mouseEvt.__proto__.__defineGetter__<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; mouseEvt.__proto__.__defineGetter__<span class="br0">&#40;</span><span class="st0">'pageX'</span>, <span class="kw2">function</span><span class="br0">&#40;</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> <span class="kw1">this</span>.<span class="me1">clientX</span> + window.<span class="me1">pageXOffset</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; mouseEvt.__proto__.__defineGetter__<span class="br0">&#40;</span><span class="st0">'pageY'</span>, <span class="kw2">function</span><span class="br0">&#40;</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> <span class="kw1">this</span>.<span class="me1">clientY</span> + window.<span class="me1">pageYOffset</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
	<p>Just include the preceding code snippet anywhere in your HTML page.  The code is pretty straight-forward and just relies on the fact that Firefox (and others) have the ability to define getters through the use of <code>.__defineGetter__(..)</code>.</p>
	<p>The <code>.pageX/Y</code> properties are read only, but it turns out that the browser will let you redefine these getters, thereby overriding their return logic.  Since the <code>.clientX/Y</code> properties appear to always report the correct value, all we have to do redefine the <code>.pageX/Y</code> getters to use a combination of <code>.clientX/Y</code> + <code>.pageX/YOffset</code>.</p>
	<p>In other words, we've redefined <code>.pageX/Y</code> to always return the position of the event (in our case, the mouse cursor since we're dealing with MouseEvents), relative to the upper-left corner of the browser window + the scrolled position of the browser -- what it should have been all along!</p>
	<p>This code doesn't hurt IE, as it won't execute in that browser, and it doesn't hurt Firefox 2 or other browsers that understand the code either, because the logic we've defined for the getters is going to be essentially the same as what the browser would have done natively anyway.</p>
	<p>I'd like to file a bug to Mozilla on this issue, but I haven't a clue as to how one goes about doing that.  If anyone knows (or wants to do it for me), feel free to speak up!</p>
	<p>Enjoy the fix!</p>
	<p>Comments welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/07/03/firefox-3-pagex-pagey-bug/feed/</wfw:commentRss>
		<slash:comments>12</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>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>Fresh Nuggets of Gimme Awesomeness</title>
		<link>http://blog.stchur.com/2008/04/01/fresh-nuggets-of-gimme-awesomeness/</link>
		<comments>http://blog.stchur.com/2008/04/01/fresh-nuggets-of-gimme-awesomeness/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 20:58:45 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Gimme]]></category>

		<guid isPermaLink="false">http://blog.stchur.com/2008/04/01/fresh-nuggets-of-gimme-awesomeness/</guid>
		<description><![CDATA[	Some really cool stuff happening with Gimme lately, especially with regards to its animation capabilities.
	I whipped together something that started off (in my head anyway) as a sort of copy of CoverFlow on Mac OS.  However, before I was finished, it had morphed into a general purpose animation-along-an-arbitrary-path-type-routine.
	This code isn't yet checked into the [...]]]></description>
			<content:encoded><![CDATA[	<p>Some really cool stuff happening with Gimme lately, especially with regards to its animation capabilities.</p>
	<p>I whipped together something that started off (in my head anyway) as a sort of copy of CoverFlow on Mac OS.  However, before I was finished, it had morphed into a general purpose animation-along-an-arbitrary-path-type-routine.</p>
	<p>This code isn't yet checked into the repository, but for anyone who is interested in taking a look, here are two different demo pages to see the "bleeding edge" of what is going on with Gimme:</p>
	<ul>
	<li><a href = "http://gimme.stchur.com/gimmeflow4.html" title = "Animation along an arbitrary path using Gimme">Animation along an arbitrary path using Gimme</a></li>
	<li><a href = "http://gimme.stchur.com/animationdemo.html" title = "Gimme Animation Demo Page">Gimme Animation Demo Page</a></li>
	</ul>
	<p>There are a few things worth nothing.  The first link is a really quick-n-dirty prototype, so there are bound to be bugs.  The page takes a few seconds to load as it is pulling remote photos from my Spaces photo album.  You'll have to wait until everything is loaded and in place to try out the demo.  Just click on any image and you'll get the idea.  You can also change the shape of the curve that the images follow by clicking on the "S Shape" button.</p>
	<p>The second link is a general animation demo page.  By providing a set of Bezier control points (comma separated coordinates / spaces separated points), you can instruct the script to plot any curve and then have the red block follow that curve.  You can also chose the AccelerationLine you want to use with the animation (note that Linear is a bad name, and should really be None -- I will fix this one day).</p>
	<p>You can even use the text area on the right side of the page to execute arbitrary custom code.  I've provided a sample that animates the red block counter-clockwise around an ellipse 2 and 1/2 times.</p>
	<p>As you can see, it doesn't take much code at all to achieve some fairly sophisticated animation with Gimme.</p>
	<p>In a future blog entry, I hope to polish up this code and provide a deeper explanation of the samples (as well as get this code checked into the repository).</p>
	<p>Comments welcome</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2008/04/01/fresh-nuggets-of-gimme-awesomeness/feed/</wfw:commentRss>
		<slash:comments>0</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>Re-routing Events in Javascript</title>
		<link>http://blog.stchur.com/2007/11/16/re-routing-events-in-javscript/</link>
		<comments>http://blog.stchur.com/2007/11/16/re-routing-events-in-javscript/#comments</comments>
		<pubDate>Fri, 16 Nov 2007 07:47:26 +0000</pubDate>
		<dc:creator>sstchur</dc:creator>
				<category><![CDATA[Advanced Javascript]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://stchur.com/blog2/2007/11/16/re-routing-events-in-javscript/</guid>
		<description><![CDATA[	Sometimes, it is desirable to re-route an event in Javascript, from its original target to some other target.  Suppose for example, you have two different elements that appear to be layered, one of top of the other, but they only appear this way because of CSS. In terms of the DOM, the elements would [...]]]></description>
			<content:encoded><![CDATA[	<p>Sometimes, it is desirable to re-route an event in Javascript, from its original target to some other target.  Suppose for example, you have two different elements that appear to be layered, one of top of the other, but they only appear this way because of CSS. In terms of the DOM, the elements would be siblings, as in:</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="sc3"><span class="re1">&lt;div</span> id = <span class="st0">&quot;elem1&quot;</span><span class="re2">&gt;</span></span>#elem1<span class="sc3"><span class="re1">&lt;/div<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;div</span> id = <span class="st0">&quot;elem2&quot;</span><span class="re2">&gt;</span></span>#elem2<span class="sc3"><span class="re1">&lt;/div<span class="re2">&gt;</span></span></span></div>
	<p>With a little CSS, that HTML might look something like this:</p>
	<p><style type = "text/css"><br />
#example1 { position: relative; margin-left: 1em; height: 8em; color: #fff; }<br />
#elem1 { position: absolute; padding: 5px; top: 0; left: 0; width: 12em; height: 6em; background: blue; }<br />
#elem2 { position: absolute; padding: 5px; top: 2em; left: 2em; width: 6em; height: 2em; background: orange; }<br />
</style></p>
	<div id = "example1" style = "position: relative; margin-left: 1em; height: 8em; color: #fff;">
	<div id = "elem1" style = "position: absolute; padding: 5px; top: 0; left: 0; width: 12em; height: 6em; background: blue;">#elem1</div>
	<div id = "elem2" style = "position: absolute; padding: 5px; top: 2em; left: 2em; width: 6em; height: 2em; background: orange;">#elem2</div>
	</div>
	<p>It should be obvious, but I'll draw attention to it again because it's important for this discussion: <i><code>#elem2</code> is not actually contained within <code>#elem1</code></i>, even though visually, it appears to be.</p>
	<p>The implications of this are significant because it means that that any events that originate at <code>#elem2</code> will <i>not</i> propagate (or bubble) up to the <code>#elem1</code>.  You might very well want them to though.</p>
	<p>For example, suppose you have an <code>click</code> event handler wired to <code>#elem1</code> like so:</p</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">var</span> elem1 = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'elem1'</span><span class="br0">&#41;</span>;<br />
elem1.<span class="me1">addEventListener</span><span class="br0">&#40;</span><span class="st0">'click'</span>, elem1Click, <span class="kw2">false</span><span class="br0">&#41;</span>;&nbsp; &nbsp;&nbsp; &nbsp;<span class="co1">// or your favorite addEvent(..) equalizer</span><br />
<span class="kw2">function</span> elem1Click<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="kw3">alert</span><span class="br0">&#40;</span>e.<span class="me1">target</span> + <span class="st0">' was clicked'</span><span class="br0">&#41;</span>;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// e.srcElement for IE</span><br />
<span class="br0">&#125;</span></div>
	<p>Clicking on <code>#elem1</code> will cause an alert, but clicking on <code>#elem2</code> won't, because <code>#elem1</code> is not an ancestor of <code>#elem2</code> and therefore, when the event that is dispatched from the 'click' event bubbles, it won't go through <code>#elem1</code>.</p>
	<p>So how do you <i>make</i> the event go through <code>#elem1</code>?  How you ensure that when a user clicks on <code>#elem2</code> the 'click' handler for <code>#elem1</code> fires?  Through event re-routing!</p>
	<h3>An event detour</h3>
	<p>It's possible to manually dispatch an event in Javascript, and as usual, there are two (modern) ways to do it:  The W3C DOM way, and the IE way.  We'll start with the W3C method.</p>
	<h3>.dispatchEvent(evtObject)</h3>
	<p>The <code>.dispatchEvent(..)</code> method takes only one argument: the event object that you wish to dispatch.  Sounds simple enough, but unfortunately it gets more complicated.</p>
	<p> In order to dispatch an event, you must first create one.  You do this through <code>document.createEvent(evtType)</code>.  But you're <i>still</i> not done.  The event object you just created needs to be initialized, which can be done in a <a href = "http://developer.mozilla.org/en/docs/DOM:document.createEvent" title = "Mozilla Developer Center (document.createEvent)">number of ways</a>.</p>
	<p>Here is a bare-bones example of creating and initializing a mouse event:</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; <span class="co1">// event type</span><br />
&nbsp; &nbsp;,<span class="kw2">false</span> &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>;</div>
	<p>At this point, you can go ahead and dispatch that lovely "click" event you just created/initialized to some DOM element of your choosing.</p>
	<div class="dean_ch" style="white-space: nowrap;">document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'myElem'</span><span class="br0">&#41;</span>.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>myEvt<span class="br0">&#41;</span>;</div>
	<p>And if all goes as planned, any "click" handlers wired to <code>#myElem</code> should fire.</p>
	<p>This is all fantastic, but it leaves a number of important questions unanswered.  Where was the mouse when the click occurred?  Was the shift key depressed at the time?  How about the ctrl key or the alt key?</p>
	<p>To include this kind of meta-data with our event object, we need to change the syntax a bit, and supply a whole <a href = "http://developer.mozilla.org/en/docs/DOM:event.initMouseEvent" title = "Mozilla Developer Center (initMouseEvent)">boat-load</a> of additional parameters.</p>
	<p>Here's an example.</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">initMouseEvent</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp;<span class="st0">'click'</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// event type</span><br />
&nbsp; &nbsp;,<span class="kw2">true</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// can bubble?</span><br />
&nbsp; &nbsp;,<span class="kw2">true</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// cancelable?</span><br />
&nbsp; &nbsp;,window &nbsp; &nbsp; &nbsp;<span class="co1">// the event's abstract view (should always be window)</span><br />
&nbsp; &nbsp;,<span class="nu0">1</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// mouse click count (or event &quot;detail&quot;)</span><br />
&nbsp; &nbsp;,<span class="nu0">100</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// event's screen x coordinate</span><br />
&nbsp; &nbsp;,<span class="nu0">200</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// event's screen y coordinate</span><br />
&nbsp; &nbsp;,<span class="nu0">100</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// event's client x coordinate</span><br />
&nbsp; &nbsp;,<span class="nu0">200</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// event's client y coordinate</span><br />
&nbsp; &nbsp;,<span class="kw2">false</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// whether or not CTRL was pressed during event</span><br />
&nbsp; &nbsp;,<span class="kw2">false</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// whether or not ALT was pressed during event</span><br />
&nbsp; &nbsp;,<span class="kw2">false</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// whether or not SHIFT was pressed during event</span><br />
&nbsp; &nbsp;,<span class="kw2">false</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// whether or not the meta key was pressed during event</span><br />
&nbsp; &nbsp;,<span class="nu0">1</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// indicates which button (if any) caused the mouse event (1 = primary button)</span><br />
&nbsp; &nbsp;,<span class="kw2">null</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="co1">// relatedTarget (only applicable for mouseover/mouseout events)</span><br />
<span class="br0">&#41;</span>;</p>
	<p><span class="co1">// now dispatch the event</span><br />
document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'myElem'</span><span class="br0">&#41;</span>.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>myEvt<span class="br0">&#41;</span>;</div>
	<p>The first thing you should notice is the use of <code>.initMouseEvent(..)</code> instead of just <code>.initEvent(..)</code>, the former taking a much more complete set of parameters with which to initialize the event.</p>
	<p>Generally speaking, you wouldn't do what I did in my example here.  The parameters I passed in were pretty arbitrary (100, 200 for screen coordinates and such).  Instead, if you're re-routing an event, you'll probably want to copy the properties of the original event.  That would look something like this (comments omitted this time for brevity).</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> clickHandler<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<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 />
&nbsp; &nbsp;myEvt.<span class="me1">initMouseEvent</span><span class="br0">&#40;</span>e.<span class="me1">type</span>, e.<span class="me1">bubbles</span>, e.<span class="me1">cancelable</span>, window, e.<span class="me1">detail</span>,<br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">screenX</span>, e.<span class="me1">screenY</span>, e.<span class="me1">clientX</span>, e.<span class="me1">clientY</span>, e.<span class="me1">ctrlKey</span>, e.<span class="me1">altKey</span>, e.<span class="me1">shiftKey</span>,<br />
&nbsp; &nbsp;&nbsp; &nbsp;e.<span class="me1">metaKey</span>, e.<span class="me1">button</span>, e.<span class="me1">relatedTarget</span><span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'someOtherElem'</span><span class="br0">&#41;</span>.<span class="me1">dispatchEvent</span><span class="br0">&#40;</span>myEvt<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<h3>.fireEvent(evtType, [evtObject])</h3>
	<p>IE handles manual event dispatching a little differently.  You're not forced to create an event object to pass into <code>.fireEvent(..)</code>.  That second parameter is optional actually.  Something like this would be acceptable (though it still begs the same question that using <code>.initEvent(..)</code> does):</p>
	<div class="dean_ch" style="white-space: nowrap;">document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'myElem'</span><span class="br0">&#41;</span>.<span class="me1">fireEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span><span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp;<span class="co1">// don't forget the &quot;on&quot;</span></div>
	<p>This would simply dispatch a "click" event to <code>#myElem</code> with a set of <a href = "http://msdn2.microsoft.com/en-us/library/ms536423.aspx" title = "MSDN (fireEvent Method)">default values</a> based on the current event object.</p>
	<p>If you want change some property of the event object (e.g. you want to force the event object to interpret the ALT key as having been depressed), then you need to create a new event object, which is done with <a href = "http://msdn2.microsoft.com/en-us/library/ms536390.aspx" title = "MSDN (document.createEventObject Method">document.createEventObject([e])</a>, and pass that into <code>.fireEvent(..)</code> as the 2nd parameter.</p>
	<div class="dean_ch" style="white-space: nowrap;"><span class="kw2">function</span> clickHandler<span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp;<span class="co1">// base this new event on the existing event object, e</span><br />
&nbsp; &nbsp;<span class="kw2">var</span> myEvt = document.<span class="me1">createEventObject</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span>;</p>
	<p>&nbsp; &nbsp;<span class="co1">// force the ALT key to appear as having been pressed</span><br />
&nbsp; &nbsp;myEvt.<span class="me1">altKey</span> = <span class="kw2">true</span>;</p>
	<p>&nbsp; &nbsp;document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">'someOtherElem'</span><span class="br0">&#41;</span>.<span class="me1">fireEvent</span><span class="br0">&#40;</span><span class="st0">'onclick'</span>, myEvt<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></div>
	<p>Now, when <code>clickHandler(..)</code> executes, it will forwards its event (or more correctly, create a new event based on the current event and dispatches it) to <code>#someOtherElem</code> while also simulating that the ALT key was pressed.</p>
	<h3>One Caveat</h3>
	<p>You might wonder why we have to create a new event instead of just truly forwarding on the existing event object (I wondered this).  To be honest, I don't know.  All I know is that in Firefox, this didn't work.  It generated one of those cryptic nsComponentSomethingOrOther errors, whereas creating a new event worked like a charm.</p>
	<p>This might not be a problem in other browsers, but I didn't bother to check, since <i>not</i> supporting Firefox is never an option for me.</p>
	<h3>An Event Re-routing Demo</h3>
	<p>To drive home the things I've been talking about in this post, I've put together a simple demo involving two sibling <code>&lt;div&gt;</code> elements, one of which will forward its "click," "mousemove," and "mousedown" events to the other.  To make the demo a little more interesting, I'll make it so that forwarded "click" events appear to have the SHIFT key pressed.</p>
	<p><a href = "/blogcode/event-rerouting/" title = "Javascript Event Re-routing Demo" target = "_blank">View the event re-routing demo</a></p>
	<p>Comments, questions, suggestions, complaints?  Speak thy mind!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.stchur.com/2007/11/16/re-routing-events-in-javscript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
