<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	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/"
		>
<channel>
	<title>Comments on: A Good Enough addEvent</title>
	<atom:link href="http://austinmatzko.com/2008/04/14/addevent-preserving-this/feed/" rel="self" type="application/rss+xml" />
	<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/</link>
	<description>A blog about philosophy, Christianity, web development and whatever else I feel like writing about.</description>
	<lastBuildDate>Thu, 16 May 2013 02:22:18 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2-RC4-18391</generator>
	<item>
		<title>By: Andra Collazo</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-216549</link>
		<dc:creator>Andra Collazo</dc:creator>
		<pubDate>Wed, 19 Dec 2012 07:32:30 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-216549</guid>
		<description>That’s probably because PPK’s contest requirements were like asking for all three of good, fast, and cheap.</description>
		<content:encoded><![CDATA[<p>That’s probably because PPK’s contest requirements were like asking for all three of good, fast, and cheap.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ranae Autry</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-216436</link>
		<dc:creator>Ranae Autry</dc:creator>
		<pubDate>Wed, 12 Dec 2012 11:25:38 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-216436</guid>
		<description>It&#039;s good to see this information in your post, i was looking the same but there was not any proper resource, thanx now i have the link which i was looking for my research. . . . . .</description>
		<content:encoded><![CDATA[<p>It&#8217;s good to see this information in your post, i was looking the same but there was not any proper resource, thanx now i have the link which i was looking for my research. . . . . .</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: A Good Enough addEvent – Il Filosofo</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-212509</link>
		<dc:creator>A Good Enough addEvent – Il Filosofo</dc:creator>
		<pubDate>Mon, 10 May 2010 15:44:54 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-212509</guid>
		<description>[...] Here is the original post:  A Good Enough addEvent – Il Filosofo [...]</description>
		<content:encoded><![CDATA[<p>[...] Here is the original post:  A Good Enough addEvent – Il Filosofo [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: The Only Guide For Dealing With Restraining Orders On The Market &#8230; &#124; JavaScript WebDev Insider</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-212498</link>
		<dc:creator>The Only Guide For Dealing With Restraining Orders On The Market &#8230; &#124; JavaScript WebDev Insider</dc:creator>
		<pubDate>Sun, 09 May 2010 06:40:29 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-212498</guid>
		<description>[...] A Good Enough addEvent – Il Filosofo [...]</description>
		<content:encoded><![CDATA[<p>[...] A Good Enough addEvent – Il Filosofo [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: javascript的事件绑定函数 at Jeekundo.com</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-211495</link>
		<dc:creator>javascript的事件绑定函数 at Jeekundo.com</dc:creator>
		<pubDate>Sun, 13 Dec 2009 11:04:38 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-211495</guid>
		<description>[...] 上面提到的这些都有提供相配套的解除绑定函数，但是大部分时候我们只需要绑定，不需要解绑，这种情况下下面这个简单的函数已经足够满足我们的需要了。 [...]</description>
		<content:encoded><![CDATA[<p>[...] 上面提到的这些都有提供相配套的解除绑定函数，但是大部分时候我们只需要绑定，不需要解绑，这种情况下下面这个简单的函数已经足够满足我们的需要了。 [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: shadedecho</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-205122</link>
		<dc:creator>shadedecho</dc:creator>
		<pubDate>Fri, 31 Oct 2008 12:44:51 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-205122</guid>
		<description>I&#039;ve actually been working on this &quot;problem&quot; of getting a good add/remove event toolset (not framework based).

Mine is admittedly a bit longer in terms of code and less &quot;graceful&quot; looking, but I think it&#039;s got coverage for a lot more of the &quot;problems&quot; that people complain about with event handler adding/removing.

The strategy I used to be able to chain any number of handlers for an event, even duplicate ones, and have the ordering and remove-ability preserved, was using a function closure chain.

Here&#039;s the claims that it makes:
1. Preserves the &quot;this&quot; in handlers to refer to the object the event was fired on.
2. Works on pretty much any browser/version (and doesn&#039;t require any browser sniffing/detection to do so, since it falls back to the old-school onXXX style)
3. Allows mutliple chained event handlers (even duplicate handlers), which execute in a predictable FIFO order, regardless of browser.  But duplicate handlers are removed in LIFO order, as I think would be expected.
4. does use expando properties (and closures) on the target object, but manages them in such a way that if an author properly calls unbindEvent() for their events when the page unloads, things should not leak (IE).

Here&#039;s also a working example of the code: &lt;a href=&quot;http://www.getify.com/test-events.html&quot; rel=&quot;nofollow&quot;&gt;http://www.getify.com/test-events.html&lt;/a&gt;.

And here&#039;s the code:
&lt;code&gt;
var UNDEF = &quot;undefined&quot;, JSFUNC = &quot;function&quot;;

function bindEvent(obj,eventName,handlerFunc) {
	eventName = eventName.toLowerCase();
	if (typeof obj[eventName] === JSFUNC) {
		(function(ename) {  // recursive function to move the chain of signatures down one link to make room for the new handler
			if (typeof obj[ename+&quot;_&quot;] === JSFUNC) { // *next* item already a chain
				arguments.callee(ename+&quot;_&quot;);  // recurse to keep shifting the chain links down
			}
			obj[ename+&quot;_&quot;] = obj[ename];  
		})(eventName+&quot;_&quot;);
		
		obj[eventName+&quot;_&quot;] = handlerFunc; // store handler signature for removal purposes
		var prev_chain = obj[eventName];
		obj[eventName] = function() { // insert new link into the chain
			prev_chain();  // &#039;recursively&#039; (through closure wrap-up) call previous link/chain -- FIFO execution
			handlerFunc(); // call new link
		};
	}
	else { // just old-school register handler, and store its signature to create the first link of the chain
		obj[eventName+&quot;_&quot;] = (obj[eventName] = handlerFunc);
	}
}

function unbindEvent(obj,eventName,handlerFunc) {
	eventName = eventName.toLowerCase();
	if (typeof obj[eventName] === JSFUNC) {  
		var last_ename = null, ename = eventName+&quot;_&quot;;  // start looking for signatures at first &quot;_&quot; level hung off the end of the event name
		while (typeof obj[ename]!==UNDEF &amp;&amp; obj[ename]!==null) {  //loop through all signatures to find the target handler to remove
			if (obj[ename] === handlerFunc) {  // target handler found, so remove its signature from the chain
				while (typeof obj[ename+&quot;_&quot;] === JSFUNC) { // keep going as long as the next higher link in the signature chain is defined
					obj[ename] = obj[ename+&quot;_&quot;];  // move the next higher link down one level to replace the existing link
					last_ename = ename; // used to keep track of which level/signature-name is the new highest one in the chain
					ename += &quot;_&quot;;  // move up one link level in the signature chain
				}
				obj[ename] = null; // the last link of the chain needs to be null&#039;d
				try { delete obj[ename]; } catch (err) { }  // and deleted
		
				if (last_ename !== null) {  // if any chain of signature links still exists, it needs to be re-wrapped into a ball of closure function calls
					var chain = obj[last_ename];  // start by capturing the function signature from the last link of the signature chain
					ename = last_ename.replace(/_$/,&quot;&quot;);   // start at the next to last element of the signature chain
					while (ename!==eventName) {  // work backwards, rolling up the closures level by level, until you reach the beginning of the chain
						(function(){    // needs a &quot;local scope block&quot; for proper closure
							var prev_chain = chain, handlerFunc = obj[ename];
							chain = function() {  // re-create the closure wrap-up function representing this link of the signature chain, save for next while-iteration
								prev_chain();  // FIFO execution
								handlerFunc();
							};
						})();
						ename = ename.replace(/_$/,&quot;&quot;);   // move back down one level of the signature chain
					} 
					obj[ename] = chain;  // entire closure chain re-created, so attach it to the main event handler property so it&#039;ll be called directly on event
				}
				break;
			}
			else { // target handler not found yet, step up one level of the signature chain
				last_ename = ename;
				ename += &quot;_&quot;;
			}
		}
		if (typeof obj[eventName+&quot;_&quot;] === UNDEF &#124;&#124; obj[eventName+&quot;_&quot;] === null) {  // clean up -- if the signature chain is now empty (all events removed), remove the main event handler too.
			obj[eventName] = null;
			try { delete obj[eventName]; } catch (err) { }
		}
	}
}
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>I&#8217;ve actually been working on this &#8220;problem&#8221; of getting a good add/remove event toolset (not framework based).</p>
<p>Mine is admittedly a bit longer in terms of code and less &#8220;graceful&#8221; looking, but I think it&#8217;s got coverage for a lot more of the &#8220;problems&#8221; that people complain about with event handler adding/removing.</p>
<p>The strategy I used to be able to chain any number of handlers for an event, even duplicate ones, and have the ordering and remove-ability preserved, was using a function closure chain.</p>
<p>Here&#8217;s the claims that it makes:<br />
1. Preserves the &#8220;this&#8221; in handlers to refer to the object the event was fired on.<br />
2. Works on pretty much any browser/version (and doesn&#8217;t require any browser sniffing/detection to do so, since it falls back to the old-school onXXX style)<br />
3. Allows mutliple chained event handlers (even duplicate handlers), which execute in a predictable FIFO order, regardless of browser.  But duplicate handlers are removed in LIFO order, as I think would be expected.<br />
4. does use expando properties (and closures) on the target object, but manages them in such a way that if an author properly calls unbindEvent() for their events when the page unloads, things should not leak (IE).</p>
<p>Here&#8217;s also a working example of the code: <a href="http://www.getify.com/test-events.html" rel="nofollow">http://www.getify.com/test-events.html</a>.</p>
<p>And here&#8217;s the code:<br />
<code><br />
var UNDEF = "undefined", JSFUNC = "function";</code></p>
<p>function bindEvent(obj,eventName,handlerFunc) {<br />
	eventName = eventName.toLowerCase();<br />
	if (typeof obj[eventName] === JSFUNC) {<br />
		(function(ename) {  // recursive function to move the chain of signatures down one link to make room for the new handler<br />
			if (typeof obj[ename+"_"] === JSFUNC) { // *next* item already a chain<br />
				arguments.callee(ename+"_");  // recurse to keep shifting the chain links down<br />
			}<br />
			obj[ename+"_"] = obj[ename];<br />
		})(eventName+"_");</p>
<p>		obj[eventName+"_"] = handlerFunc; // store handler signature for removal purposes<br />
		var prev_chain = obj[eventName];<br />
		obj[eventName] = function() { // insert new link into the chain<br />
			prev_chain();  // 'recursively' (through closure wrap-up) call previous link/chain -- FIFO execution<br />
			handlerFunc(); // call new link<br />
		};<br />
	}<br />
	else { // just old-school register handler, and store its signature to create the first link of the chain<br />
		obj[eventName+"_"] = (obj[eventName] = handlerFunc);<br />
	}<br />
}</p>
<p>function unbindEvent(obj,eventName,handlerFunc) {<br />
	eventName = eventName.toLowerCase();<br />
	if (typeof obj[eventName] === JSFUNC) {<br />
		var last_ename = null, ename = eventName+"_";  // start looking for signatures at first "_" level hung off the end of the event name<br />
		while (typeof obj[ename]!==UNDEF &amp;&amp; obj[ename]!==null) {  //loop through all signatures to find the target handler to remove<br />
			if (obj[ename] === handlerFunc) {  // target handler found, so remove its signature from the chain<br />
				while (typeof obj[ename+"_"] === JSFUNC) { // keep going as long as the next higher link in the signature chain is defined<br />
					obj[ename] = obj[ename+"_"];  // move the next higher link down one level to replace the existing link<br />
					last_ename = ename; // used to keep track of which level/signature-name is the new highest one in the chain<br />
					ename += "_";  // move up one link level in the signature chain<br />
				}<br />
				obj[ename] = null; // the last link of the chain needs to be null'd<br />
				try { delete obj[ename]; } catch (err) { }  // and deleted</p>
<p>				if (last_ename !== null) {  // if any chain of signature links still exists, it needs to be re-wrapped into a ball of closure function calls<br />
					var chain = obj[last_ename];  // start by capturing the function signature from the last link of the signature chain<br />
					ename = last_ename.replace(/_$/,"");   // start at the next to last element of the signature chain<br />
					while (ename!==eventName) {  // work backwards, rolling up the closures level by level, until you reach the beginning of the chain<br />
						(function(){    // needs a "local scope block" for proper closure<br />
							var prev_chain = chain, handlerFunc = obj[ename];<br />
							chain = function() {  // re-create the closure wrap-up function representing this link of the signature chain, save for next while-iteration<br />
								prev_chain();  // FIFO execution<br />
								handlerFunc();<br />
							};<br />
						})();<br />
						ename = ename.replace(/_$/,"");   // move back down one level of the signature chain<br />
					}<br />
					obj[ename] = chain;  // entire closure chain re-created, so attach it to the main event handler property so it'll be called directly on event<br />
				}<br />
				break;<br />
			}<br />
			else { // target handler not found yet, step up one level of the signature chain<br />
				last_ename = ename;<br />
				ename += "_";<br />
			}<br />
		}<br />
		if (typeof obj[eventName+"_"] === UNDEF || obj[eventName+"_"] === null) {  // clean up -- if the signature chain is now empty (all events removed), remove the main event handler too.<br />
			obj[eventName] = null;<br />
			try { delete obj[eventName]; } catch (err) { }<br />
		}<br />
	}<br />
}<br />
</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tino Zijdel</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-197597</link>
		<dc:creator>Tino Zijdel</dc:creator>
		<pubDate>Fri, 18 Apr 2008 21:50:16 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-197597</guid>
		<description>&lt;em&gt;It’s rare that one developer “owns” the window.onload event.&lt;em&gt;

No-one should &#039;own&#039; that event in such circumstances; you&#039;ll need global conventions such as &#039;onload events should be registered using this-and-such interface&#039;.

I was just trying to illustrate that even though it is good that &lt;em&gt;you&lt;/em&gt; try to play nice, other scripts might not and can screw up yours (or each other) anyway.

My more general &#039;criticism&#039; is about the &#039;good enough&#039; part of this article: I argued that for most people your original addEvent wrapper might still be &#039;good enough&#039; and even just using object.onevent=function is &#039;good enough&#039; in most cases. It just all depends on what you think is important and on what you actually need. You just need to be aware of the limitations of the solution you implement, and in my humble opinion most people are just not knowledgeable enough for that.

In general I think that &#039;brevity&#039; should not be such a heavy factor when evaluating cross-browser eventhandling solutions, especially not if you already include several KB of script for other generic purposes.</description>
		<content:encoded><![CDATA[<p><em>It’s rare that one developer “owns” the window.onload event.</em><em></em></p>
<p>No-one should &#8216;own&#8217; that event in such circumstances; you&#8217;ll need global conventions such as &#8216;onload events should be registered using this-and-such interface&#8217;.</p>
<p>I was just trying to illustrate that even though it is good that <em>you</em> try to play nice, other scripts might not and can screw up yours (or each other) anyway.</p>
<p>My more general &#8216;criticism&#8217; is about the &#8216;good enough&#8217; part of this article: I argued that for most people your original addEvent wrapper might still be &#8216;good enough&#8217; and even just using object.onevent=function is &#8216;good enough&#8217; in most cases. It just all depends on what you think is important and on what you actually need. You just need to be aware of the limitations of the solution you implement, and in my humble opinion most people are just not knowledgeable enough for that.</p>
<p>In general I think that &#8216;brevity&#8217; should not be such a heavy factor when evaluating cross-browser eventhandling solutions, especially not if you already include several KB of script for other generic purposes.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: scottandrew</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-197541</link>
		<dc:creator>scottandrew</dc:creator>
		<pubDate>Fri, 18 Apr 2008 20:03:53 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-197541</guid>
		<description>&lt;em&gt;I think it’s a bad sign if you don’t know what other scripts are doing on your page&lt;/em&gt;

Try working on a site like where multiple departments with multiple developers own discrete sections of a large website. It&#039;s rare that one developer &quot;owns&quot; the window.onload event.

Being able to overload event handlers safely is far more valuable than the ability to detach handler functions. If you&#039;re attaching so many handlers that you have to detach them to prevent leakage, I&#039;d say that&#039;s a poor design to begin with.</description>
		<content:encoded><![CDATA[<p><em>I think it’s a bad sign if you don’t know what other scripts are doing on your page</em></p>
<p>Try working on a site like where multiple departments with multiple developers own discrete sections of a large website. It&#8217;s rare that one developer &#8220;owns&#8221; the window.onload event.</p>
<p>Being able to overload event handlers safely is far more valuable than the ability to detach handler functions. If you&#8217;re attaching so many handlers that you have to detach them to prevent leakage, I&#8217;d say that&#8217;s a poor design to begin with.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tino Zijdel</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-197370</link>
		<dc:creator>Tino Zijdel</dc:creator>
		<pubDate>Fri, 18 Apr 2008 06:56:48 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-197370</guid>
		<description>I think it&#039;s a bad sign if you don&#039;t know what other scripts are doing on your page (they just as well might overwrite your addEvent function!) ;)

Besides that I personally never use window.onload; I have a DomLoaded class (in my toolbox) and register onload functions to that using DomLoaded.addLoadEvent()</description>
		<content:encoded><![CDATA[<p>I think it&#8217;s a bad sign if you don&#8217;t know what other scripts are doing on your page (they just as well might overwrite your addEvent function!) <img src='http://austinmatzko.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Besides that I personally never use window.onload; I have a DomLoaded class (in my toolbox) and register onload functions to that using DomLoaded.addLoadEvent()</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Dustin Diaz</title>
		<link>http://austinmatzko.com/2008/04/14/addevent-preserving-this/comment-page-1/#comment-197359</link>
		<dc:creator>Dustin Diaz</dc:creator>
		<pubDate>Fri, 18 Apr 2008 03:54:50 +0000</pubDate>
		<guid isPermaLink="false">http://www.ilfilosofo.com/?p=441#comment-197359</guid>
		<description>This is good and makes perfect sense. I also came up with a very short and concise addEvent in my article to &lt;a href=&quot;http://www.dustindiaz.com/javascript-no-no/&quot; rel=&quot;nofollow&quot;&gt;write better JavaScript&lt;/a&gt;. It even does a simple branch so you&#039;re not always detecting the object in question (W3 vs IE).
All in all, you make a good case. And I too rarely ever use removeEvent... it seems like a waste of time for smaller websites :)</description>
		<content:encoded><![CDATA[<p>This is good and makes perfect sense. I also came up with a very short and concise addEvent in my article to <a href="http://www.dustindiaz.com/javascript-no-no/" rel="nofollow">write better JavaScript</a>. It even does a simple branch so you&#8217;re not always detecting the object in question (W3 vs IE).<br />
All in all, you make a good case. And I too rarely ever use removeEvent&#8230; it seems like a waste of time for smaller websites <img src='http://austinmatzko.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
</channel>
</rss>
