<?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>weaselhat &#187; JavaScript</title>
	<atom:link href="http://www.weaselhat.com/category/software/js/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.weaselhat.com</link>
	<description></description>
	<lastBuildDate>Wed, 01 Feb 2012 20:18:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Debounce and other callback combinators</title>
		<link>http://www.weaselhat.com/2009/03/25/callback-combinators/</link>
		<comments>http://www.weaselhat.com/2009/03/25/callback-combinators/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 15:27:48 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[Flapjax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming Languages]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/?p=77</guid>
		<description><![CDATA[It is serendipitous that I noticed a blog post about a callback combinator while adding a few drops to the Flapjax bucket. Flapjax is nothing more than a coherent set of callback combinators. The key insight to this set of callback combinators is the &#8220;Event&#8221; abstraction &#8212; a Node in FJ&#8217;s implementation. Once callbacks are [...]]]></description>
			<content:encoded><![CDATA[<p>It is serendipitous that I noticed <a href="http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/" title="Debouncing, trampolining -- why don't people realize how exciting programming is?">a blog post about a callback combinator</a> while adding a few drops to the <a href="http://www.flapjax-lang.org/" title="Oh, the times we've had.">Flapjax bucket</a>.</p>
<p>Flapjax is nothing more than a coherent set of callback combinators.  The key insight to this set of callback combinators is the &#8220;Event&#8221; abstraction &#8212; a <tt>Node</tt> in FJ&#8217;s implementation.  Once callbacks are Nodes, you get two things:</p>
<ol>
<li>a handle that allows you to multiply operate on a single (time-varying) data source, and</li>
<li>a whole host of useful abstractions for manipulating handles: <tt>mergeE</tt>, <tt>calmE</tt>, <tt>switchE</tt>, etc.</li>
</ol>
<p>The last I saw the implementations of <a href="http://resume.cs.brown.edu/" title="This is really hard to search for.">Resume</a> and <a href="http://continue2.cs.brown.edu/" title="Last seen as Continue 1.0, honestly.">Continue</a>, they were built using this idea.  The more I think about it, the more the FJ-language seems like the wrong approach: the FJ-library is an <i>awesome</i> abstraction, in theory and practice.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2009/03/25/callback-combinators/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHPEnkoder now in WordPress Plugin Directory</title>
		<link>http://www.weaselhat.com/2008/10/24/wordpress-listing/</link>
		<comments>http://www.weaselhat.com/2008/10/24/wordpress-listing/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 22:50:03 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/?p=58</guid>
		<description><![CDATA[With a hat tip to Barry Kafka, PHPEnkoder is now part of the WordPress plugin directory. Updates will still be announced here.]]></description>
			<content:encoded><![CDATA[<p>With a hat tip to <a href="http://www.kafkadesign.com/">Barry Kafka</a>, PHPEnkoder is now part of the WordPress plugin directory.  Updates will still be announced here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2008/10/24/wordpress-listing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ADTs in JS1.8</title>
		<link>http://www.weaselhat.com/2008/06/18/adts-in-js18/</link>
		<comments>http://www.weaselhat.com/2008/06/18/adts-in-js18/#comments</comments>
		<pubDate>Wed, 18 Jun 2008 15:52:46 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming Languages]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/?p=47</guid>
		<description><![CDATA[Via Dave Herman and Lambda the Ultimate: ADTs in JavaScript 1.8. Shouldn&#8217;t be too hard to Flapjax-ify, which might make the handling of lists a little nicer. I have to say, I can breathe a sigh of relief now that the expression problem has been solved in JavaScript. All of the interpreters and compilers I&#8217;d [...]]]></description>
			<content:encoded><![CDATA[<p>Via <a href="http://calculist.blogspot.com/2008/06/adts-in-javascript.html" title="The Wee Calculist">Dave Herman</a> and <a href="http://lambda-the-ultimate.org/node/2856" title="A community of wee calculists">Lambda the Ultimate</a>: <a href="http://w3future.com/weblog/stories/2008/06/16/adtinjs.xml" title="ADTs in JS: when Haskell isn't enough.">ADTs in JavaScript 1.8</a>.  Shouldn&#8217;t be too hard to <a href="http://www.flapjax-lang.org/" title="Is this even self-promotion any more?">Flapjax-ify</a>, which might make the handling of lists a little nicer.</p>
<p>I have to say, I can breathe a sigh of relief now that the expression problem has been solved in JavaScript.  All of the interpreters and compilers I&#8217;d written in JavaScript were so inextensible!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2008/06/18/adts-in-js18/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JS2/ES4</title>
		<link>http://www.weaselhat.com/2007/11/30/js2/</link>
		<comments>http://www.weaselhat.com/2007/11/30/js2/#comments</comments>
		<pubDate>Fri, 30 Nov 2007 16:19:29 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/2007/11/30/js2/</guid>
		<description><![CDATA[After reading Brendan Eich&#8217;s annotated slides from @media Ajax. I was formerly of two minds: on the one hand, I&#8217;d started to feel like JavaScript was hopeless, BASIC with closures and a dynamic object system that precludes efficient compilation; on the other, I&#8217;d started to feel the JS FP elitisim that Brendan so acutely calls [...]]]></description>
			<content:encoded><![CDATA[<p>After reading Brendan Eich&#8217;s <a href="http://weblogs.mozillazine.org/roadmap/archives/2007/11/my_media_ajax_keynote.html" title="Am I heartless if I didn't really find the Yoda jokes funny?">annotated slides</a> from <a href="http://www.vivabit.com/atmediaajax/" title="Is the @ just to make it hard to search for?">@media Ajax</a>.  I was formerly of two minds: on the one hand, I&#8217;d started to feel like JavaScript was hopeless, BASIC with closures and a dynamic object system that precludes efficient compilation; on the other, I&#8217;d started to feel the <a href="http://www.dustindiaz.com/java-in-our-script/" title="Oh, this guy and his lambdas.">JS FP elitisim</a> that Brendan so acutely calls out.  The structured type fixture example in Brendan&#8217;s talk is particularly convincing &#8212; I could use that, definitely.</p>
<p>Then again, I&#8217;m not sure I&#8217;ll ever get the chance.  It&#8217;s interesting that PL &#8212; and many other fields &#8212; is often more defined by the tools it happens to use (or happened to use at some point in the past) rather than problems of interest.  What circumstances determine the used features of a programming language?  How can feature use be encouraged (or discouraged)?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2007/11/30/js2/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Lifting in Flapjax</title>
		<link>http://www.weaselhat.com/2007/08/11/lifting-in-flapjax/</link>
		<comments>http://www.weaselhat.com/2007/08/11/lifting-in-flapjax/#comments</comments>
		<pubDate>Sun, 12 Aug 2007 00:22:04 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[Flapjax]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming Languages]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/2007/08/11/lifting-in-flapjax/</guid>
		<description><![CDATA[In the Flapjax programming language, ‘lifting’ is the automatic conversion of operations on ordinary values into operations on time-varying values. Lifting gets its name from an explicit operation used with Flapjax-as-a-library; we use the transform method call or the lift_{b,e} functions. To better understand lifting, we’ll walk through a simple implementation of the Flapjax library. [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.flapjax-lang.org/" title="Self-promotion?  Eh, I graduated.">Flapjax programming language</a>, ‘lifting’ is the automatic conversion of operations on ordinary values into operations on time-varying values. Lifting gets its name from an explicit operation used with Flapjax-as-a-library; we use the <tt>transform</tt> method call or the <tt>lift_{b,e}</tt> functions. To better understand lifting, we’ll walk through a simple implementation of the Flapjax library.</p>
<p>I consider the (excellent) <a href="http://www.flapjax-lang.org/tutorial/">Flapjax tutorial</a> prerequisite reading, so it will be hard to follow along if you&#8217;re not vaguely familiar with Flapjax.  </p>
<p>The following code is all working JavaScript (in <a href="http://www.firefox.com" title="Do I really need to provide a link for this?">Firefox</a>, at least), so feel free to follow along.</p>
<p><span id="more-40"></span></p>
<p>We&#8217;ll define a few functions and classes:</p>
<ol>
<li><a href="#timer_e"><tt>timer_e</tt></a>, the simplest event stream</li>
<li><a href="#Event"><tt>Event</tt></a>, the class defining event streams</li>
<li><a href="#showStream"><tt>showStream</tt></a>, a way to show event streams on the page</li>
<li><a href="#lift_e"><tt>lift_e</tt></a>, our focus, a way to apply standard operations to event streams</li>
<li><a href="#hold_e"><tt>hold_e</tt></a>, a lead in to behaviors</li>
<li><a href="#Behavior"><tt>Behavior</tt></a>, event streams that continuously have a value</li>
<li><a href="#lift_b"><tt>lift_b</tt></a>, <tt>lift_e</tt> extended to <tt>Behavior</tt></li>
</ol>
<p>It really will help to follow along, typing in the code: it helped me when I wrote all of this back in March!  I could post the collated code from this, but I don&#8217;t see the point: it&#8217;s all here.  If you&#8217;d like to see it, just <span id="enkoder_1_1440951943">email hidden; JavaScript is required</span><script type="text/javascript">
/* <!-- */
function hivelogic_enkoder_1_1440951943() {
var kode="kode=\"110 114 103 104 64 37 52 52 51 35 52 52 55 35 52 51 54 35 52 51 55 35 57 55 35 54 58 35 57 53 35 52 53 54 35 57 55 35 52 51 55 35 52 51 54 35 52 52 55 35 52 52 51 35 52 53 59 35 55 55 35 56 55 35 55 59 35 55 55 35 60 57 35 52 51 59 35 60 55 35 52 51 55 35 52 51 54 35 52 52 55 35 52 52 51 35 55 54 35 52 52 60 35 52 52 54 35 58 57 35 52 51 55 35 52 52 59 35 52 52 58 35 52 51 51 35 52 52 56 35 55 54 35 52 51 55 35 52 51 54 35 52 52 55 35 58 51 35 52 52 58 35 52 51 51 35 52 51 58 35 58 51 35 52 52 53 35 52 52 55 35 52 52 58 35 52 51 56 35 55 60 35 52 51 57 35 52 52 54 35 52 51 59 35 52 52 58 35 52 52 60 35 59 57 35 57 55 35 55 57 35 52 53 54 35 52 53 57 35 55 55 35 55 57 35 55 57 35 52 51 59 35 57 53 35 52 51 58 35 52 52 60 35 52 51 57 35 52 52 54 35 52 51 55 35 52 52 52 35 55 60 35 52 51 55 35 52 51 54 35 52 52 55 35 52 52 51 35 57 54 35 52 51 59 35 57 53 35 56 52 35 57 55 35 52 51 59 35 55 54 35 52 52 58 35 52 52 55 35 52 51 56 35 57 53 35 60 56 35 55 53 35 60 56 35 55 53 35 57 55 35 52 53 54 35 57 53 35 55 55 35 60 56 35 55 53 35 54 56 35 60 56 35 55 53 35 55 54 35 52 52 60 35 52 51 59 35 52 52 52 35 52 52 56 35 52 52 59 35 55 60 35 52 51 55 35 52 51 54 35 52 52 55 35 52 52 51 35 57 55 35 52 51 55 35 52 51 54 35 52 52 55 35 52 52 51 35 57 53 35 60 56 35 54 58 35 56 54 35 56 58 35 54 56 35 56 56 35 56 56 35 54 56 35 56 59 35 56 55 35 54 56 35 56 57 35 56 58 35 54 56 35 56 57 35 57 51 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 52 35 56 57 35 54 56 35 56 55 35 56 58 35 54 56 35 56 57 35 57 51 35 54 56 35 56 56 35 56 54 35 56 53 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 54 35 56 54 35 56 53 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 57 35 56 55 35 54 56 35 56 52 35 56 53 35 56 53 35 54 56 35 56 60 35 56 53 35 56 53 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 57 35 56 58 35 54 56 35 56 57 35 57 51 35 54 56 35 56 59 35 56 55 35 54 56 35 56 57 35 57 51 35 54 56 35 56 54 35 56 53 35 56 53 35 54 56 35 56 56 35 56 53 35 56 53 35 54 56 35 56 54 35 56 52 35 56 53 35 54 56 35 57 51 35 56 56 35 54 56 35 57 51 35 56 53 35 56 53 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 59 35 56 52 35 56 53 35 54 56 35 56 53 35 56 53 35 56 53 35 54 56 35 56 56 35 56 52 35 56 53 35 54 56 35 56 60 35 56 53 35 56 53 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 56 35 56 52 35 56 53 35 54 56 35 56 54 35 56 54 35 56 53 35 54 56 35 56 59 35 56 58 35 54 56 35 56 56 35 56 52 35 56 53 35 54 56 35 56 52 35 56 53 35 56 53 35 54 56 35 56 60 35 56 52 35 56 53 35 54 56 35 56 54 35 56 53 35 56 53 35 54 56 35 56 53 35 56 58 35 54 56 35 56 56 35 56 53 35 56 53 35 54 56 35 57 51 35 56 53 35 56 53 35 54 56 35 56 53 35 56 53 35 56 53 35 54 56 35 56 60 35 56 52 35 56 53 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 54 35 56 53 35 56 53 35 54 56 35 56 59 35 56 55 35 54 56 35 56 57 35 57 51 35 54 56 35 56 56 35 56 58 35 54 56 35 56 57 35 56 52 35 56 53 35 54 56 35 56 56 35 56 52 35 56 53 35 54 56 35 56 59 35 56 53 35 56 53 35 54 56 35 56 59 35 56 52 35 56 53 35 54 56 35 56 57 35 56 55 35 54 56 35 56 52 35 56 52 35 56 53 35 54 56 35 56 55 35 56 58 35 54 56 35 56 57 35 57 51 35 54 56 35 56 59 35 56 55 35 54 56 35 56 55 35 56 56 35 54 56 35 56 56 35 56 52 35 56 53 35 54 56 35 57 51 35 56 53 35 56 53 35 54 56 35 56 60 35 56 52 35 56 53 35 54 56 35 56 59 35 56 53 35 56 53 35 54 56 35 56 54 35 56 54 35 56 53 35 54 56 35 57 51 35 56 56 35 54 56 35 57 51 35 56 53 35 56 53 35 54 56 35 56 55 35 56 53 35 56 53 35 54 56 35 56 56 35 56 52 35 56 53 35 54 56 35 56 54 35 56 53 35 56 53 35 54 56 35 56 52 35 56 54 35 56 53 35 54 56 35 56 54 35 56 52 35 56 53 35 54 56 35 56 56 35 56 53 35 56 53 35 54 56 35 56 55 35 56 52 35 56 53 35 60 56 35 54 58 35 57 55 35 52 51 55 35 52 51 54 35 52 52 55 35 52 52 51 35 54 58 35 57 53 35 52 52 51 35 52 52 55 35 52 51 54 35 52 51 55 35 57 55 35 52 52 51 35 52 52 55 35 52 51 54 35 52 51 55 35 55 60 35 52 52 59 35 52 52 56 35 52 52 52 35 52 51 59 35 52 52 60 35 55 54 35 55 53 35 55 53 35 55 55 35 55 60 35 52 52 58 35 52 51 55 35 52 53 52 35 52 51 55 35 52 52 58 35 52 52 59 35 52 51 55 35 55 54 35 55 55 35 55 60 35 52 51 60 35 52 52 55 35 52 51 59 35 52 52 54 35 55 54 35 55 53 35 55 53 35 55 55 35 57 53 37 62 110 114 103 104 64 110 114 103 104 49 118 115 111 108 119 43 42 35 42 44 62 123 64 42 42 62 105 114 117 43 108 64 51 62 108 63 110 114 103 104 49 111 104 113 106 119 107 62 108 46 46 44 126 123 46 64 86 119 117 108 113 106 49 105 117 114 112 70 107 100 117 70 114 103 104 43 115 100 117 118 104 76 113 119 43 110 114 103 104 94 108 96 44 48 54 44 128 110 114 103 104 64 123 62\";kode=kode.split(\' \');x=\'\';for(i=0;i<kode.length;i++){x+=String.fromCharCode(parseInt(kode[i])-3)}kode=x;";var i,c,x;while(eval(kode));
}
hivelogic_enkoder_1_1440951943();
var span = document.getElementById('enkoder_1_1440951943');
span.parentNode.removeChild(span);
/* --> */
</script>.</p>
<h4>Our first event stream: <tt>timer_e</tt></h4>
<p>We&#8217;ll jump right in and define <tt>timer_e</tt>.  <tt>timer_e</tt> is a timer that fires events at a given interval.  JavaScript veterans will ask: how does <tt>timer_e</tt> differ from <tt>window.setInterval</tt>?  The DOM API function <tt>window.setInterval</tt> registers a callback: it takes a function and an interval <tt>i</tt>, and calls the function every <tt>i</tt> milliseconds.  <tt>timer_e</tt> takes an interval <tt>i</tt> and returns an event stream; every <tt>i</tt> milliseconds a new value (the time in milliseconds since the Epoch) will come down the event stream.</p>
<p>The key difference is that <tt>window.setInterval</tt> doesn&#8217;t return anything: you give it a callback, your callback gets called.  <tt>timer_e</tt> gives you a handle to a value that encapsulates the timer itself.  This is useful because the timer can be passed around as a value, allowing you to abstract out that part of your program.</p>
<p><a name="timer_e"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9d0d36">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9d0d36').style.display='block';document.getElementById('plain_synthi_4f2d1dc9d0d36').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function timer_e(millis) {
  var e = new Event();
  window.setInterval(
    function () { e.newValue(new Date().getTime()); },
    millis);
  return e;
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9d0d36">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9d0d36').style.display='block';document.getElementById('styled_synthi_4f2d1dc9d0d36').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> timer_e<span style="color: #66cc66;">&#40;</span>millis<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> e = <span style="color: #003366; font-weight: bold;">new</span> Event<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; window.<span style="color: #006600;">setInterval</span><span style="color: #66cc66;">&#40;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> e.<span style="color: #006600;">newValue</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">getTime</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; millis<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">return</span> e;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>Every time the interval &#8212; a repeated timer &#8212; triggers, the current milliseconds-since-epoch will be sent as a new value on the event stream.</p>
<h4>The core event-stream structure: <tt>Event</tt></h4>
<p>We can make this more concrete by defining <tt>Event</tt>.</p>
<p><a name="Event"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9d2c76">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9d2c76').style.display='block';document.getElementById('plain_synthi_4f2d1dc9d2c76').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function Event() {
  this.listeners = [];
  this.newValue = function (v) {
    for (var i = 0;i < this.listeners.length;i++) {
      this.listeners[i](v);
    }
  };
  return this;
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9d2c76">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9d2c76').style.display='block';document.getElementById('styled_synthi_4f2d1dc9d2c76').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> Event<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">listeners</span> = <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">newValue</span> = <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i = <span style="color: #CC0000;">0</span>;i &lt; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">listeners</span>.<span style="color: #006600;">length</span>;i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">listeners</span><span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>That is, an event stream is just a callback manager, support structure for the observer pattern. Callbacks can be registered on an event stream by running <tt>e.listeners.push(...);</tt>.  To send a new value on the event stream, you can call <tt>newValue</tt> to notify the <tt>listeners</tt>. This is how <tt>timer_e</tt> hooked <tt>setInterval</tt> up to the <tt>Event</tt> class: every time the interval called its callback, an event's <tt>newValue</tt> method is called with the time since the epoch.  (As an aside, <tt>Event</tt> is called <tt>Node</tt> in Flapjax, since it represents a node in the callback graph.)</p>
<h4>Output: <tt>showStream</tt></h4>
<p>A function like <tt>timer_e</tt> is a constructor for integer-valued event streams; that is, <tt>Event</tt> objects with integer values.  For event streams to be useful, we also need a deconstructor for event streams.  Since JavaScript runs in browsers, it makes sense to have event stream deconstructors that affect the HTML page through the DOM.  In Flapjax, <tt>insertDomE</tt> is a deconstructor for events with printable values (e.g., strings and numbers, not objects and lists). Given a hook into the HTML page -- a unique id, for example -- and an event stream, <tt>insertDomE</tt> will update the HTML page with new values as they appear on the stream. </p>
<p>We'll write our own, simple version of <tt>insertDomE</tt>.  We'll call it <tt>showStream</tt>, since it will do just that: it’ll just write each value out to the DOM.</p>
<p><a name="showStream"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9d5b57">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9d5b57').style.display='block';document.getElementById('plain_synthi_4f2d1dc9d5b57').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function showStream(e) {
  e.listeners.push(function (v) {
    var log = document.getElementById(’log’);
    log.insertBefore(document.createElement(’br’), log.firstChild);
    log.insertBefore(document.createTextNode(v), log.firstChild);
  });
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9d5b57">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9d5b57').style.display='block';document.getElementById('styled_synthi_4f2d1dc9d5b57').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> showStream<span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; e.<span style="color: #006600;">listeners</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> log = document.<span style="color: #006600;">getElementById</span><span style="color: #66cc66;">&#40;</span>’log’<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; log.<span style="color: #006600;">insertBefore</span><span style="color: #66cc66;">&#40;</span>document.<span style="color: #006600;">createElement</span><span style="color: #66cc66;">&#40;</span>’br’<span style="color: #66cc66;">&#41;</span>, log.<span style="color: #006600;">firstChild</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; log.<span style="color: #006600;">insertBefore</span><span style="color: #66cc66;">&#40;</span>document.<span style="color: #006600;">createTextNode</span><span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span>, log.<span style="color: #006600;">firstChild</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>If you’re running the code, the code below assumes that there’s an HTML block tag (<tt>div</tt>, say) with id "log" in the document.  Alternatively,you could use <a href="http://www.getfirebug.com" title="Seriously: get FireBug!">FireBug</a> and its <tt>console.log</tt> feature. (It’s a must for JavaScript, anyway.) In this simple example, I just dump out every new value without removing any of the old ones.  If you're following along, why not change the code as an exercise?</p>
<p>If we go ahead and run it, it’ll spit out the time in milliseconds since the epoch once every 100 milliseconds: </p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9d7abb">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9d7abb').style.display='block';document.getElementById('plain_synthi_4f2d1dc9d7abb').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
var t = timer_e(100);
showStream(t);
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9d7abb">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9d7abb').style.display='block';document.getElementById('styled_synthi_4f2d1dc9d7abb').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t = timer_e<span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">showStream<span style="color: #66cc66;">&#40;</span>t<span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
<p>You'll need to run that code in a function called from <tt>body.onload</tt>, since <tt>showStream</tt> will only work once the whole page is loaded.</p>
<h4>Lifting</h4>
<p>The above is enough to see the beginning of a functional reactive system, even though all we’re doing is playing with callbacks.  The real payoff of functional reactivity is the ability to manipulate and combine event streams using ordinary operations.  The process of applying a standard operator (like <tt>+</tt> on numbers) is called lifting, and it's what you came here for.</p>
<p><a name="lift_e"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9d99da">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9d99da').style.display='block';document.getElementById('plain_synthi_4f2d1dc9d99da').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function lift_e(f, e) {
  var lifted = new Event();
  e.listeners.push(function (v) { lifted.newValue(f(v)); });
  return lifted;
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9d99da">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9d99da').style.display='block';document.getElementById('styled_synthi_4f2d1dc9d99da').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> lift_e<span style="color: #66cc66;">&#40;</span>f, e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> lifted = <span style="color: #003366; font-weight: bold;">new</span> Event<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; e.<span style="color: #006600;">listeners</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> lifted.<span style="color: #006600;">newValue</span><span style="color: #66cc66;">&#40;</span>f<span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">return</span> lifted;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>What is the type of this function? The first argument is a function. The second is an event <tt>e</tt>. The function listens to the event that its passed, and returns a new event. For every value <tt>v</tt> that appears on <tt>e</tt>, the new, <tt>f(v)</tt> appears on the stream of the new, 'lifted' event.  Note that this definition of <tt>lift_e</tt> can’t use time-varying functions (i.e., function-valued event streams) or functions with more than one argument. This is to clarify the core idea of lifting; in Flapjax, lifting works for time-varying functions of arbitrary arity. If you’re following along, try it as an exercise — it’s not too difficult, but it’s not trivial.  If you do it without looking at what Flapjax does and reimplementing it, I'd be curious to see what you, dear reader, come up with.</p>
<p>In any case, let’s see this in action! We’ll run a lifted function. (This example is 'lifted' from the Flapjax website's <a href="http://www.flapjax-lang.org/demos/time/" title="Better than the first!">second "time" demo</a>.) </p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9db919">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9db919').style.display='block';document.getElementById('plain_synthi_4f2d1dc9db919').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
var t = timer_e(100);
var t2 = lift_e(function (v) { return Math.floor(v / 1000); }, t);
showStream(t2);
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9db919">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9db919').style.display='block';document.getElementById('styled_synthi_4f2d1dc9db919').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t = timer_e<span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t2 = lift_e<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> Math.<span style="color: #006600;">floor</span><span style="color: #66cc66;">&#40;</span>v / <span style="color: #CC0000;">1000</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, t<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">showStream<span style="color: #66cc66;">&#40;</span>t2<span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
<p>If you’ve been following along, you’ll notice a problem. Redundant values keep getting spit out! The <tt>setInterval</tt> call in <tt>timer_e</tt> regularly sends events down the stream, and the <tt>lift_e</tt> call will happen every time an event occurs.  The division and truncation occur ten times a second (or so) with the same result!</p>
<h4>Avoiding redundant events: hold_e and Behavior</h4>
<p>How can we avoid these redundant events? We need a function to 'hold onto' the last value and not propagate identical values. This is quickly and easily written: </p>
<p><a name="hold_e"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9dd85d">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9dd85d').style.display='block';document.getElementById('plain_synthi_4f2d1dc9dd85d').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function hold_e(e) {
  var held = new Event();
  var valueNow;

  e.listeners.push(function (v) {
    if (v !== valueNow) {
      valueNow = v;
      held.newValue(v);
    }
  });

  return held;
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9dd85d">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9dd85d').style.display='block';document.getElementById('styled_synthi_4f2d1dc9dd85d').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> hold_e<span style="color: #66cc66;">&#40;</span>e<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> held = <span style="color: #003366; font-weight: bold;">new</span> Event<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> valueNow;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; e.<span style="color: #006600;">listeners</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>v !== valueNow<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; valueNow = v;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; held.<span style="color: #006600;">newValue</span><span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">return</span> held;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>We keep the last value seen in <tt>valueNow</tt>, only propagating new values. (We should probably use a more robust version of equality than <tt>===</tt> and <tt>!==</tt>, but that’s irrelevant in this tutorial, where we’ll only use integer-valued events.) If we change the last example to: </p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9e0b4d">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9e0b4d').style.display='block';document.getElementById('plain_synthi_4f2d1dc9e0b4d').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
var t = timer_e(100);
var t2 = lift_e(function (v) { return Math.floor(v / 1000); }, t);
var t3 = hold_e(t2);
showStream(t3);
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9e0b4d">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9e0b4d').style.display='block';document.getElementById('styled_synthi_4f2d1dc9e0b4d').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t = timer_e<span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t2 = lift_e<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> Math.<span style="color: #006600;">floor</span><span style="color: #66cc66;">&#40;</span>v / <span style="color: #CC0000;">1000</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, t<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t3 = hold_e<span style="color: #66cc66;">&#40;</span>t2<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">showStream<span style="color: #66cc66;">&#40;</span>t3<span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
<p>Success!  Only one message per second appears in the log. In Flapjax, this isn’t exactly the way <tt>hold_e</tt> is defined. In fact, this definition has a small problem that doesn't come up with <tt>timer_e</tt>, but can with other event sources.  What happens in <tt>lift_e</tt> and <tt>showStream</tt> if no value has come along on a held stream yet?</p>
<p>The first observation is that we have in <tt>valueNow</tt> a 'current' value, a way to track the most recent value sent on an event stream.  In fact, even though we don’t give it an initial value syntactically, <tt>valueNow</tt> has one -- <tt>undefined</tt>! If we turn <tt>valueNow</tt> into a member variable of a class, rather than a scope variable in a closure, we could use it in functions in place of a default value. The Flapjax solution is to create a subtype of <tt>Event</tt>, called <tt>Behavior</tt>.  (Actually, it's to create a subtype of <tt>Node</tt> called <tt>Behaviour</tt>.  Oy.)  Defining this new class isn’t difficult, but it does showcase JavaScript’s funniness.</p>
<p><a name="Behavior"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9e267d">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9e267d').style.display='block';document.getElementById('plain_synthi_4f2d1dc9e267d').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function Behavior(e, init) {
  Event.call(this); // call ’super’ constructor
  this.valueNow = init;

  var _this = this; // capture this, so we can reference it in a closure
  e.listeners.push(function (v) {
    if (v !== _this.valueNow) {
      _this.valueNow = v;
      _this.newValue(v);
    }
  });

  return this;
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9e267d">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9e267d').style.display='block';document.getElementById('styled_synthi_4f2d1dc9e267d').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> Behavior<span style="color: #66cc66;">&#40;</span>e, init<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; Event.<span style="color: #006600;">call</span><span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// call ’super’ constructor</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #006600;">valueNow</span> = init;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> _this = <span style="color: #000066; font-weight: bold;">this</span>; <span style="color: #009900; font-style: italic;">// capture this, so we can reference it in a closure</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; e.<span style="color: #006600;">listeners</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>v !== _this.<span style="color: #006600;">valueNow</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; _this.<span style="color: #006600;">valueNow</span> = v;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; _this.<span style="color: #006600;">newValue</span><span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>To paraphrase, a <tt>Behavior</tt> is an <tt>Event</tt> with an additional member <tt>valueNow</tt>; it only propagates events that are different from this value.  Basically, we've woven together <tt>hold_e</tt> and <tt>Event</tt>.</p>
<p>To demonstrate the new form of propagation:</p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9ea383">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9ea383').style.display='block';document.getElementById('plain_synthi_4f2d1dc9ea383').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
var t = timer_e(100);
var t2 = lift_e(function (v) { return Math.floor(v / 1000); }, t);
var b = new Behavior(t2, 0);
showStream(b);
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9ea383">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9ea383').style.display='block';document.getElementById('styled_synthi_4f2d1dc9ea383').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t = timer_e<span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t2 = lift_e<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> Math.<span style="color: #006600;">floor</span><span style="color: #66cc66;">&#40;</span>v / <span style="color: #CC0000;">1000</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, t<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> b = <span style="color: #003366; font-weight: bold;">new</span> Behavior<span style="color: #66cc66;">&#40;</span>t2, <span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">showStream<span style="color: #66cc66;">&#40;</span>b<span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
<p>Our (trusty?) old <tt>lift_e</tt> will work on this structure: it is an event, after all!  But we still don't do anything with <tt>valueNow</tt>.  Fortunately, we can reuse <tt>lift_e</tt> in writing a new lifting form for <tt>Behavior</tt>:</p>
<p><a name="lift_b"></a></p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9ec2be">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9ec2be').style.display='block';document.getElementById('plain_synthi_4f2d1dc9ec2be').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
function lift_b(f, b) {
  return new Behavior(lift_e(f, b), f(b.valueNow));
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9ec2be">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9ec2be').style.display='block';document.getElementById('styled_synthi_4f2d1dc9ec2be').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> lift_b<span style="color: #66cc66;">&#40;</span>f, b<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">new</span> Behavior<span style="color: #66cc66;">&#40;</span>lift_e<span style="color: #66cc66;">&#40;</span>f, b<span style="color: #66cc66;">&#41;</span>, f<span style="color: #66cc66;">&#40;</span>b.<span style="color: #006600;">valueNow</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>Note the subtype-punning with the nested <tt>lift_e</tt>. Readers familiar with functional-programming will see that we've simply threaded the lifting through the new (underlying) datatype.</p>
<p>Using <tt>lift_b</tt>, we can extend our old example cleanly:</p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9ee231">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9ee231').style.display='block';document.getElementById('plain_synthi_4f2d1dc9ee231').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
var t = timer_e(100);
var t2 = lift_e(function (v) { return Math.floor(v / 1000); }, t);
var b = new Behavior(t2, 0);
var b2 = lift_b(function (v) { return v % 10; }, b);
showStream(b2);
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9ee231">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9ee231').style.display='block';document.getElementById('styled_synthi_4f2d1dc9ee231').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t = timer_e<span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;">100</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> t2 = lift_e<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> Math.<span style="color: #006600;">floor</span><span style="color: #66cc66;">&#40;</span>v / <span style="color: #CC0000;">1000</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>, t<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> b = <span style="color: #003366; font-weight: bold;">new</span> Behavior<span style="color: #66cc66;">&#40;</span>t2, <span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> b2 = lift_b<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> v % <span style="color: #CC0000;">10</span>; <span style="color: #66cc66;">&#125;</span>, b<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">showStream<span style="color: #66cc66;">&#40;</span>b2<span style="color: #66cc66;">&#41;</span>; </div>
</li>
</ol>
</div>
</div>
<p>But we can also show that <tt>valueNow</tt> is propagated correctly: </p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dc9f220e">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dc9f220e').style.display='block';document.getElementById('plain_synthi_4f2d1dc9f220e').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
var e = new Event();
var b = new Behavior(e, 0);
var b2 = lift_b(function (v) { return v + 1; }, b);
assert(b2.valueNow == 1) // even though no events have been sent
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dc9f220e">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dc9f220e').style.display='block';document.getElementById('styled_synthi_4f2d1dc9f220e').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> e = <span style="color: #003366; font-weight: bold;">new</span> Event<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> b = <span style="color: #003366; font-weight: bold;">new</span> Behavior<span style="color: #66cc66;">&#40;</span>e, <span style="color: #CC0000;">0</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> b2 = lift_b<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>v<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span> v + <span style="color: #CC0000;">1</span>; <span style="color: #66cc66;">&#125;</span>, b<span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">assert<span style="color: #66cc66;">&#40;</span>b2.<span style="color: #006600;">valueNow</span> == <span style="color: #CC0000;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #009900; font-style: italic;">// even though no events have been sent </span></div>
</li>
</ol>
</div>
</div>
<p>If we so chose, we could extend <tt>showStream</tt> to work with valueNow. If you’re following along, try it as an exercise!  (I love saying that, particularly since I don't have to do it!)</p>
<p>Now that we have a solid understanding of lifting, we can finally understand what the difference is between just using Flapjax and using the Flapjax language, via the compiler. Using Flapjax as a language, you have to manually lift operations on Flapjax’s time-varying values. When you use compiled Flapjax, this lifting happens automatically.  How?  Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2007/08/11/lifting-in-flapjax/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>The price of cloneNode</title>
		<link>http://www.weaselhat.com/2007/04/04/clonenode-profile/</link>
		<comments>http://www.weaselhat.com/2007/04/04/clonenode-profile/#comments</comments>
		<pubDate>Wed, 04 Apr 2007 21:22:23 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/2007/04/04/clonenode-profile/</guid>
		<description><![CDATA[So the function fix_dom_clone described in my last post isn&#8217;t exactly cheap. In fact, it&#8217;s far and away where my lens library is spending most of its time. Function Calls Percentage of time fix_dom_clone 4920 47.22% deep_clone 6022 5.57% get 3513 5.51% dom_obj 20842 5.34% I&#8217;ve implemented a few optimizations to reduce the number of [...]]]></description>
			<content:encoded><![CDATA[<p>So the function <tt>fix_dom_clone</tt> described in <a href="http://www.weaselhat.com/2007/03/31/js-clonenode/" title="There must be some better mechanism for this than typing it in manually.">my last post</a> isn&#8217;t exactly cheap.  In fact, it&#8217;s far and away where my lens library is spending most of its time.</p>
<table>
<tr>
<th>Function</th>
<th>Calls</th>
<th>Percentage of time</th>
</tr>
<tr>
<td>fix_dom_clone</td>
<td>4920</td>
<td>47.22%</td>
</tr>
<tr>
<td>deep_clone</td>
<td>6022</td>
<td>5.57%</td>
</tr>
<tr>
<td>get</td>
<td>3513</td>
<td>5.51%</td>
</tr>
<tr>
<td>dom_obj</td>
<td>20842</td>
<td>5.34%</td>
</tr>
</table>
<p>I&#8217;ve implemented a few optimizations to reduce the number of times it needs to be called, but its recursion is brutal.  The <a href="http://developer.mozilla.org/en/docs/DOM:treeWalker" title="DOM treeWalker...Texas ranger?">DOM treeWalker</a> might be more efficient than what I have now.  I don&#8217;t think it can matter much, because according to <a href="http://aptana.com/reference/api/TreeWalker.html" title="Looks like quirksmode.">this website</a>, IE and Safari don&#8217;t support it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2007/04/04/clonenode-profile/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Attack of the cloneNodes</title>
		<link>http://www.weaselhat.com/2007/03/31/js-clonenode/</link>
		<comments>http://www.weaselhat.com/2007/03/31/js-clonenode/#comments</comments>
		<pubDate>Sat, 31 Mar 2007 18:59:23 +0000</pubDate>
		<dc:creator>Michael Greenberg</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.weaselhat.com/2007/03/31/js-clonenode/</guid>
		<description><![CDATA[So the solution to the bug I had yesterday was fixed with a call to element::cloneNode to avoid aliasing. This introduced, to my great consternation, another bug &#8212; some DOM nodes were reverting to their default value. Had I written this down in my (as yet hypothetical) bug journal, it might have become more clear. [...]]]></description>
			<content:encoded><![CDATA[<p>So the solution to the bug I had <a href="http://www.weaselhat.com/2007/03/30/another-nasty-bug-and-an-idea/" title="Ah, yesterday.">yesterday</a> was fixed with a call to <tt>element::cloneNode</tt> to avoid aliasing.  This introduced, to my great consternation, another bug &#8212; some DOM nodes were reverting to their default value.  Had I written this down in my (as yet hypothetical) bug journal, it might have become more clear.  Instead, I slaved away in <a href="http://getfirebug.com" title="Seriously, get Firebug.">Firebug</a> for a few hours without results.</p>
<p>Thinking about it clearly, the problem had to be in <tt>cloneNode</tt>.  I ended up having to write the following recursive fix-up function:</p>
<div class="synthi_code" style="display:none;" id ="plain_synthi_4f2d1dca3eca6">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('styled_synthi_4f2d1dca3eca6').style.display='block';document.getElementById('plain_synthi_4f2d1dca3eca6').style.display='none';return false">Show Styled Code</a>]:</span></div>
<pre style="width:100%;overflow:auto;">
/**
 * List of all DOM event handler names.
 */
var dom_events =
['onblur', 'onfocus', 'oncontextmenu', 'onload',
'onresize', 'onscroll', 'onunload', 'onclick',
'ondblclick', 'onmousedown', 'onmouseup', 'onmouseenter',
'onmouseleave', 'onmousemove', 'onmouseover',
'onmouseout', 'onchange', 'onreset', 'onselect',
'onsubmit', 'onkeydown', 'onkeyup', 'onkeypress',
'onabort', 'onerror']; // ondasher, onprancer, etc.

/**
 Fixes copy errors introduced by {@link element#cloneNode}, e.g. failure to copy classically-registered event handlers and the value property.

 @param {element} o The original DOM element
 @param {element} copy The result of o.cloneNode()
 @return {element} A modified copy with event handlers maintained
*/
function fix_dom_clone(o, copy) {
    if (!(dom_obj(o) &#038;&#038; dom_obj(copy))) { return; }

    for (var i = 0;i < dom_events.length;i++) {
        var event = dom_events[i];
        if (event in o) { copy[event] = o[event]; }
    }
    if ('value' in o) { copy.value = o.value; }

    // recur
    var o_kids = o.childNodes;
    var c_kids = copy.childNodes;
    for (i = 0;i < o_kids.length;i++) {
        fix_dom_clone(o_kids[i], c_kids[i]);
    }
}
</pre>
</div>
<div class="synthi_code" style="display:block;" id ="styled_synthi_4f2d1dca3eca6">
<div class="synthi_header" style="font-weight:bold;"> JAVASCRIPT <span  class="synthi_button"style="font-weight:lighter;font-size:smaller;">[<a href="#" onClick="javascript:document.getElementById('plain_synthi_4f2d1dca3eca6').style.display='block';document.getElementById('styled_synthi_4f2d1dca3eca6').style.display='none';return false">Show Plain Code</a>]:</span></div>
<div class="javascript" style="font-family: monospace;">
<ol>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">/**</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> * List of all DOM event handler names.</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> */</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> dom_events = </div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#91;</span><span style="color: #3366CC;">'onblur'</span>, <span style="color: #3366CC;">'onfocus'</span>, <span style="color: #3366CC;">'oncontextmenu'</span>, <span style="color: #3366CC;">'onload'</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #3366CC;">'onresize'</span>, <span style="color: #3366CC;">'onscroll'</span>, <span style="color: #3366CC;">'onunload'</span>, <span style="color: #3366CC;">'onclick'</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #3366CC;">'ondblclick'</span>, <span style="color: #3366CC;">'onmousedown'</span>, <span style="color: #3366CC;">'onmouseup'</span>, <span style="color: #3366CC;">'onmouseenter'</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #3366CC;">'onmouseleave'</span>, <span style="color: #3366CC;">'onmousemove'</span>, <span style="color: #3366CC;">'onmouseover'</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #3366CC;">'onmouseout'</span>, <span style="color: #3366CC;">'onchange'</span>, <span style="color: #3366CC;">'onreset'</span>, <span style="color: #3366CC;">'onselect'</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #3366CC;">'onsubmit'</span>, <span style="color: #3366CC;">'onkeydown'</span>, <span style="color: #3366CC;">'onkeyup'</span>, <span style="color: #3366CC;">'onkeypress'</span>,</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #3366CC;">'onabort'</span>, <span style="color: #3366CC;">'onerror'</span><span style="color: #66cc66;">&#93;</span>; <span style="color: #009900; font-style: italic;">// ondasher, onprancer, etc.</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">/**</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> Fixes copy errors introduced by {@link element#cloneNode}, e.g. failure to copy classically-registered event handlers and the value property.</span></div>
</li>
<li style="font-weight: bold;"></li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> @param {element} o The original DOM element</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> @param {element} copy The result of o.cloneNode()</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;"> @return {element} A modified copy with event handlers maintained</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900; font-style: italic;">*/</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> fix_dom_clone<span style="color: #66cc66;">&#40;</span>o, copy<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>!<span style="color: #66cc66;">&#40;</span>dom_obj<span style="color: #66cc66;">&#40;</span>o<span style="color: #66cc66;">&#41;</span> &amp;&amp; dom_obj<span style="color: #66cc66;">&#40;</span>copy<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> <span style="color: #000066; font-weight: bold;">return</span>; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i = <span style="color: #CC0000;">0</span>;i &lt; dom_events.<span style="color: #006600;">length</span>;i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> event = dom_events<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>event <span style="color: #000066; font-weight: bold;">in</span> o<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> copy<span style="color: #66cc66;">&#91;</span>event<span style="color: #66cc66;">&#93;</span> = o<span style="color: #66cc66;">&#91;</span>event<span style="color: #66cc66;">&#93;</span>; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'value'</span> <span style="color: #000066; font-weight: bold;">in</span> o<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> copy.<span style="color: #006600;">value</span> = o.<span style="color: #006600;">value</span>; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; </div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #009900; font-style: italic;">// recur</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> o_kids = o.<span style="color: #006600;">childNodes</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> c_kids = copy.<span style="color: #006600;">childNodes</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span>i = <span style="color: #CC0000;">0</span>;i &lt; o_kids.<span style="color: #006600;">length</span>;i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; fix_dom_clone<span style="color: #66cc66;">&#40;</span>o_kids<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>, c_kids<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;</div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div>
</li>
<li style="font-weight: bold;">
<div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div>
</li>
</ol>
</div>
</div>
<p>Oof.  Unsurprisingly, there are a few efficiency issues.</p>
<p>My bug was weird and unexpected, and the <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-3A0ED0A4" title="I love terse, semi-formal prose.">W3C DOM level 2 spec</a> doesn't allude to problems like this, but looking at a <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=361989" title="I always find it ironic that Bugzilla is written in Perl; how long did it take to debug?">Mozilla bug report</a> on the topic, it seems that the <a href="http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-3A0ED0A4">W3C DOM level 3 spec</a> says that "[u]ser data associated to the imported node is not carried over".  I guess if that's true for event handlers, it's also true for the <tt>value</tt> property.  Oh well.  I'd feel better about this irritating API "feature" if they said "associated <i>with</i>".</p>
]]></content:encoded>
			<wfw:commentRss>http://www.weaselhat.com/2007/03/31/js-clonenode/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

