<?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>Ian Bicking: a blog &#187; Javascript</title>
	<atom:link href="http://blog.ianbicking.org/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ianbicking.org</link>
	<description></description>
	<lastBuildDate>Sat, 31 Dec 2011 00:12:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Javascript on the server AND the client is not a big deal</title>
		<link>http://blog.ianbicking.org/2011/03/30/js-on-server-and-client-is-not-a-big-deal/</link>
		<comments>http://blog.ianbicking.org/2011/03/30/js-on-server-and-client-is-not-a-big-deal/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 22:09:24 +0000</pubDate>
		<dc:creator>Ian</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=245</guid>
		<description><![CDATA[All the cool kids love Node.js. I&#8217;ve used it a little, and it&#8217;s fine; I was able to do what I wanted to do, and it wasn&#8217;t particularly painful. It&#8217;s fun to use something new, and it&#8217;s relatively straight-forward to get started so it&#8217;s an emotionally satisfying experience. There are several reasons you might want [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>All the cool kids love <a class="reference external" href="http://nodejs.org/">Node.js</a>.  I&#8217;ve used it a little, and it&#8217;s fine; I was able to do what I wanted to do, and it wasn&#8217;t particularly painful.  It&#8217;s fun to use something new, and it&#8217;s relatively straight-forward to get started so it&#8217;s an <em>emotionally satisfying</em> experience.</p>
<p>There are several reasons you might want to use Node.js, and I&#8217;ll ignore many of them, but I want to talk about one in particular:</p>
<blockquote><p>
Javascript on the client and the server!</p></blockquote>
<p>Is this such a great feature?  I think not&#8230;</p>
<div class="section" id="you-only-need-to-know-one-language">
<h2>You only need to know one language!</h2>
<p>Sure.  Yay ignorance!  But really, this is <em>fine</em> but unlikely to be relevant to any current potential audience for Node.js.  If you are shooting for an very-easy-to-learn client-server programming system, Node.js isn&#8217;t it.  Maybe <a class="reference external" href="http://couchapp.org/">Couch</a> or something similar has that potential?  But I digress.</p>
<p>It&#8217;s not easy to have expertise at multiple languages.  But it&#8217;s not <em>that hard</em>.  It&#8217;s considerably harder to have expertise at <em>multiple platforms</em>.  Node.js gives you one language across client and server, but <em>not</em> one platform.  Node.js programming doesn&#8217;t <em>feel</em> like the browser environment.  They do adopt many conventions when it&#8217;s reasonable, but even then it&#8217;s not always the case &#8212; in particular because many browser APIs are the awkward product of C++ programmers exposing things to Javascript, and you don&#8217;t want to reproduce those same APIs if you don&#8217;t have to (and Node.js doesn&#8217;t have to!) &#8212; an example is the event pattern in Node, which is similar to a browser but less obtuse.</p>
</div>
<div class="section" id="you-get-to-share-libraries">
<h2>You get to share libraries!</h2>
<p>First: the same set of libraries is probably not applicable.  If you can do it on the client then you probably don&#8217;t <em>have</em> to do it on the server, and vice versa.</p>
<p>But sometimes the same libraries are useful.  Can you really share them?  Browser libraries are often hard to use elsewhere because they rely on browser APIs.  These APIs are frequently <em>impossible to implement in Javascript</em>.</p>
<p>Actually they are possible to implement in Javascript using <a class="reference external" href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy">Proxies</a> (or maybe some other new and not-yet-standard Javascript features). But not in Node.js, which uses V8, and V8 is a pretty conservative implementation of the Javascript language. (<strong>Update</strong>: <a class="reference external" href="http://blog.ianbicking.org/2011/03/30/js-on-server-and-client-is-not-a-big-deal/comment-page-1/#comment-194005">it is noted</a> that you can <a class="reference external" href="https://github.com/isaacs/node-proxy/tree/master/src">implement proxies</a> &#8212; in this case a C++ extension to Node)</p>
<p>Besides these unimplementable APIs, it is also just a different environment.  There is the trivial: the <tt class="docutils literal"><span class="pre">window</span></tt> object in the browser has a Node.js equivalent, but it&#8217;s not named <tt class="docutils literal"><span class="pre">window</span></tt>. Performance is different &#8212; Node has long-running processes, the browser <em>might</em>.  Node can have blocking calls, which are useful even if you can&#8217;t use them at runtime (e.g., <tt class="docutils literal"><span class="pre">require()</span></tt>); but you can&#8217;t really have any of these at any time on the browser.  And then of course all the system calls, <em>none</em> of which you can use in the browser.</p>
<p>All these may simply be surmountable challenges, through modularity, mocking, abstractions, and so on&#8230; but ultimately I think the motivation is lacking: the domain of changing a live-rendered DOM isn&#8217;t the same as producing bytes to put onto a socket.</p>
</div>
<div class="section" id="you-can-work-fluidly-across-client-and-server">
<h2>You can work fluidly across client and server!</h2>
<p>If anything I think this is <em>dangerous</em> rather than <em>useful</em>.  The client and the server are different places, with different expectations.  Any vagueness about that boundary is <em>wrong</em>.</p>
<p>It&#8217;s wrong from a security perspective, as the security assumptions are nearly opposite on the two platforms.  The client trusts itself, and the server trusts itself, and both should hold the other in suspicion (though the client can be more trusting because the <em>browser</em> doesn&#8217;t trust the client code).</p>
<p>But it&#8217;s also the wrong way to treat HTTP.  HTTP is pretty simple until you try to make it simpler.  Efforts to make it simpler mostly make it more complicated.  HTTP lets you send serialized data back and forth to a server, with a bunch of metadata and other do-dads.  And that&#8217;s all neat, but you should always be thinking about <em>sending</em> information.  And never <em>sharing</em> information.  It&#8217;s not a fluid boundary, and code that touches HTTP needs to be explicit about it and not pretend it is equivalent to any other non-network operation.</p>
<p>Certainly you don&#8217;t <em>need</em> two implementation languages to keep your mind clear.  But it doesn&#8217;t hurt.</p>
</div>
<div class="section" id="you-can-do-validation-the-same-way-on-the-client-and-server">
<h2>You can do validation the same way on the client and server!</h2>
<p>One of the things people frequently bring up is that you can validate data on the client and server using the same code.  And of course, what web developer hasn&#8217;t been a little frustrated that they have to implement validation twice?</p>
<p>Validation on the client is primarily a <em>user experience</em> concern, where you focus on bringing attention to problems with a form, and helping the user resolve those problems.  You may be able to avoid errors entirely with an input method that avoids the problem (e.g., if a you have a slider for a numeric input, you don&#8217;t have to worry about the user inputing a non-numeric value).</p>
<p>Once the form is submitted, if you&#8217;ve done thorough client-side validation you can also avoid <em>friendly</em> server-side validation.  Of course all your client-side validation could be avoided through a malicious client, but you don&#8217;t need to give a friendly error message in that case, you can simply bail out with a simple 400 Bad Request error.</p>
<p>At that point there&#8217;s not much in common between these two kinds of validation &#8212; the client is all user experience, and the server is all data integrity.</p>
</div>
<div class="section" id="you-can-do-server-side-javascript-as-a-fallback-for-the-client">
<h2>You can do server-side Javascript as a fallback for the client!</h2>
<p>Writing for clients without Javascript is becoming increasingly less relevant, and if we aren&#8217;t <em>there</em> yet, then we&#8217;ll certainly <em>get there</em> soon.  It&#8217;s only a matter of time, the writing is on the wall. Depending on the project you might have to put in workarounds, but we should keep those concerns out of architecture decisions.  Maintaining crazy hacks is <em>not</em> worth it. There&#8217;s so many terrible hacks that have turned into frameworks, and frameworks that have justified themselves because of the problems they solved that no longer matter&#8230; Node.js deserves better than to be one of those.</p>
</div>
<div class="section" id="in-conclusion-or-whatever">
<h2>In Conclusion Or Whatever</h2>
<p>I&#8217;m not saying Node.js is <em>bad</em>.  There are other arguments for it, and you don&#8217;t need to make <em>any</em> argument for it if you just feel like using it.  It&#8217;s fun to do something new.  And I&#8217;m as optimistic about Javascript as anyone.  But this one argument, I do not think it is very good.</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2011/03/30/js-on-server-and-client-is-not-a-big-deal/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Doctest.js &amp; Callbacks</title>
		<link>http://blog.ianbicking.org/2010/09/12/doctest-js-callbacks/</link>
		<comments>http://blog.ianbicking.org/2010/09/12/doctest-js-callbacks/#comments</comments>
		<pubDate>Sun, 12 Sep 2010 23:08:40 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=239</guid>
		<description><![CDATA[Many years ago I wrote a fairly straight-forward port of Python&#8217;s doctest to Javascript. I thought it was cool, but I didn&#8217;t really talk about it that much. Especially because I knew it had one fatal flaw: it was very unfriendly towards programming with callbacks, and Javascript uses a lot of callbacks. On a recent [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Many years ago I wrote a fairly straight-forward port of Python&#8217;s <a class="reference external" href="http://docs.python.org/library/doctest.html">doctest</a> to Javascript.  I thought it was cool, but I didn&#8217;t really talk about it that much.  Especially because I knew it had one fatal flaw: it was very unfriendly towards programming with callbacks, and Javascript uses a lot of callbacks.</p>
<p>On a recent flight I decided to look at it again, and realized fixing that one flaw wasn&#8217;t actually a big deal.  So now doctest.js really works.  And I think it works well: <a class="reference external" href="http://ianb.github.com/doctestjs">doctest.js (reborn)</a>.</p>
<p>I have yet to really use doctest.js on more than a couple real cases, and as I do (or you do?) I expect to tweak it more to make it flow well. But having tried a couple of examples I am particularly liking how it can be used with callbacks.</p>
<p>Testing with callbacks is generally a tricky thing.  You want to make assertions, but they happen entirely separately from the test runner&#8217;s own loop, and your callbacks may not run at all if there&#8217;s a failure.</p>
<p>I came upon some tests recently that used <a class="reference external" href="http://pivotal.github.com/jasmine/">Jasmine</a>, a <a class="reference external" href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD-style</a> test framework.  I&#8217;m <a class="reference external" href="http://blog.ianbicking.org/behavior-driven-programming.html">not a big fan of BDD</a> but I&#8217;m fairly new to serious Javascript development so I&#8217;m trying to withhold judgement.  The flow of the tests is a bit peculiar until you realize that it&#8217;s for async reasons.  I&#8217;ll try to show something that roughly approximates a real test of an XMLHttpRequest API call:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
it<span class="br0">&#40;</span><span class="st0">&quot;should give us no results&quot;</span>, function<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; runs<span class="br0">&#40;</span>function <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; var callback = createSpy<span class="br0">&#40;</span><span class="st0">'callback for results'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; $.<span class="me1">ajax</span><span class="br0">&#40;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; url: <span class="st0">'/search'</span>,<br />
&nbsp; &nbsp; &nbsp; data: <span class="br0">&#123;</span>q: <span class="st0">&quot;query unlikely to match anything&quot;</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; &nbsp; dataType: <span class="st0">&quot;json&quot;</span>,<br />
&nbsp; &nbsp; &nbsp; success: callback<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; waits<span class="br0">&#40;</span>someTimeout<span class="br0">&#41;</span>;<br />
&nbsp; runs<span class="br0">&#40;</span>function <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; expect<span class="br0">&#40;</span>callback<span class="br0">&#41;</span>.<span class="me1">toHaveBeenCalled</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; expect<span class="br0">&#40;</span>callback.<span class="me1">mostRecentCall</span>.<span class="me1">args</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">length</span><span class="br0">&#41;</span>.<span class="me1">toEqual</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>So, the basic pattern is <tt class="docutils literal"><span class="pre">it()</span></tt> creates a group of tests, and each call to <tt class="docutils literal"><span class="pre">run()</span></tt> is a set of items to call sequentially.  Then between these run blocks you can have signals to the runner to wait for some result, either a timeout (which is fragile), or you can setup specific conditions.</p>
<p>Another popular test runner is <a class="reference external" href="http://docs.jquery.com/Qunit">QUnit</a>; it&#8217;s popular particularly because it&#8217;s what jQuery uses, and my own impression is that QUnit is just very simple and so least likely to piss you off.</p>
<p>QUnit has its own style for async:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw3">test</span><span class="br0">&#40;</span><span class="st0">&quot;should give us no results&quot;</span>, function <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; stop<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; expect<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;<br />
&nbsp; $.<span class="me1">ajax</span><span class="br0">&#40;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; url: <span class="st0">'/search'</span>,<br />
&nbsp; &nbsp; data: <span class="br0">&#123;</span>q: <span class="st0">&quot;query unlikely to match anything&quot;</span><span class="br0">&#125;</span>,<br />
&nbsp; &nbsp; dataType: <span class="st0">&quot;json&quot;</span>,<br />
&nbsp; &nbsp; success: function <span class="br0">&#40;</span>result<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; ok<span class="br0">&#40;</span>result.<span class="me1">length</span> == <span class="nu0">0</span>, <span class="st0">'No results'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; start<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p><tt class="docutils literal"><span class="pre">stop()</span></tt> confused me for a bit until I realized what they were really referring to stopping the <em>test runner</em>; of course the function continues on regardless.  What will happen is that the function will return, but nothing will have really been tested &#8212; the <tt class="docutils literal"><span class="pre">success</span></tt> callback will not have been run, and <em>cannot</em> run until all Javascript execution stops and control is given back to the browser.  So the test runner will use <tt class="docutils literal"><span class="pre">setTimeout</span></tt> to let time pass before the test continues.  In this case it will continue once <tt class="docutils literal"><span class="pre">start()</span></tt> is called. And <tt class="docutils literal"><span class="pre">expect()</span></tt> also makes it fail if it didn&#8217;t get at least one assertion during that interval &#8212; it would otherwise be easy to simply miss an assertion (though in this example it would be okay because if the success callback isn&#8217;t invoked then <tt class="docutils literal"><span class="pre">start()</span></tt> will never be called, and the runner will timeout and signal that as a failure).</p>
<p>So&#8230; now for doctest.js.  Note that doctest.js isn&#8217;t &quot;plain&quot; Javascript, it looks like what an interactive Javascript session might look like (I&#8217;ve used shell-style prompts instead of typical console prompts, because the consoles didn&#8217;t exist when first I wrote this, and because <tt class="docutils literal"><span class="pre">&gt;&gt;&gt;/...</span></tt> kind of annoy me anyway).</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ success = Spy<span class="br0">&#40;</span><span class="st0">'success'</span>, <span class="br0">&#123;</span>writes: true<span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
$ $.<span class="me1">ajax</span><span class="br0">&#40;</span><span class="br0">&#123;</span><br />
&gt; &nbsp; url: <span class="st0">'/search'</span>,<br />
&gt; &nbsp; data: <span class="br0">&#123;</span>q: <span class="st0">&quot;query unlikely to match anything&quot;</span><span class="br0">&#125;</span>,<br />
&gt; &nbsp; dataType: <span class="st0">&quot;json&quot;</span>,<br />
&gt; &nbsp; success: success.<span class="me1">func</span><br />
&gt; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
$ success.<span class="me1">wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
success<span class="br0">&#40;</span><span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>With doctest.js you still get a fairly linear feel &#8212; it&#8217;s similar to how Jasmine works, except every <tt class="docutils literal"><span class="pre">$</span></tt> prompt is potentially a place where the loop can be released so something async can happen.  Each prompt is equivalent to <tt class="docutils literal"><span class="pre">run()</span></tt> (though unless you call wait, directly or indirectly, everything will run in sequence).</p>
<p>There&#8217;s also an implicit assertion for each stanza, which is anything that is written must be matched (<tt class="docutils literal"><span class="pre">{writes:</span> <span class="pre">true}</span></tt> makes the spy/mock object write out any invocations).  This makes it much harder to miss something in your tests.</p>
<p>I&#8217;ve never actually found Python&#8217;s doctest to be a particularly good way to write docs, and I don&#8217;t expect any different from doctest.js, but I find it a very nice way to <em>write</em> and <em>run</em> tests&#8230; and while Python&#8217;s doctest is essentially abandoned and lacks many features to make it a more humane testing environment, maybe doctest.js can do better.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/09/12/doctest-js-callbacks/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Javascript Status Message Display</title>
		<link>http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/</link>
		<comments>http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 18:03:15 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/</guid>
		<description><![CDATA[In a little wiki I&#8217;ve been playing with I&#8217;ve been trying out little ideas that I&#8217;ve had but haven&#8217;t had a place to actually implement them. One is how notification messages work. I&#8217;m sure other people have done the same thing, but I thought I&#8217;d describe it anyway. A common pattern is to accept a [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>In a <a class="reference external" href="http://www.bitbucket.org/ianb/pickywiki/">little wiki I&#8217;ve been playing with</a> I&#8217;ve been trying out little ideas that I&#8217;ve had but haven&#8217;t had a place to actually implement them.  One is how notification messages work.  I&#8217;m sure other people have done the same thing, but I thought I&#8217;d describe it anyway.</p>
<p>A <a class="reference external" href="http://blog.ianbicking.org/web-application-patterns-status-notification.html">common pattern</a> is to accept a POST request and then redirect the user to some page, setting a status message.  Typically the status message is either set in a cookie or in the session, then the standard template for the application has some code to check for a message and display it.</p>
<p>The problem with this is that this breaks all caching &#8212; at any time any page can have some message injected into it, basically for no reason at all.  So I thought: why not do the whole thing in Javascript?  The server will set a cookie, but only Javascript will read it.</p>
<p>The code goes like this; on the server (easily translated into any framework):</p>
<div class="dean_ch" style="white-space: wrap;"><br />
resp.<span class="me1">set_cookie</span><span class="br0">&#40;</span><span class="st0">'flash_message'</span>, <span class="kw3">urllib</span>.<span class="me1">quote</span><span class="br0">&#40;</span>msg<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>I quote the message because it can contain characters unsafe for cookies, and URL quoting is a particularly easy quoting to apply.</p>
<p>Then I have this Javascript (using jQuery):</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$<span class="br0">&#40;</span>function <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; // Anything <span class="kw1">in</span> $<span class="br0">&#40;</span>function...<span class="br0">&#41;</span> <span class="kw1">is</span> run on page load<br />
&nbsp; &nbsp; var flashMsg = readCookie<span class="br0">&#40;</span><span class="st0">'flash_message'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>flashMsg<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; flashMsg = unescape<span class="br0">&#40;</span>flashMsg<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; var el = $<span class="br0">&#40;</span><span class="st0">'&lt;div id=&quot;flash-message&quot;&gt;'</span>+<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'&lt;div id=&quot;flash-message-close&quot;&gt;'</span>+<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'&lt;a title=&quot;dismiss this message&quot; '</span>+<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'id=&quot;flash-message-button&quot; href=&quot;#&quot;&gt;X&lt;/a&gt;&lt;/div&gt;'</span>+<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flashMsg + <span class="st0">'&lt;/div&gt;'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">'a#flash-message-button'</span>, el<span class="br0">&#41;</span>.<span class="me1">bind</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'click'</span>, function <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span>this.<span class="me1">parentNode</span>.<span class="me1">parentNode</span><span class="br0">&#41;</span>.<span class="me1">remove</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">'#body'</span><span class="br0">&#41;</span>.<span class="me1">prepend</span><span class="br0">&#40;</span>el<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; eraseCookie<span class="br0">&#40;</span><span class="st0">'flash_message'</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Note that I&#8217;ve decided to treat the flash message as HTML.  I don&#8217;t see a strong risk of injection attack in this case, though I must admit I&#8217;m a little unclear about what the normal policies are for cross-domain cookie setting.</p>
<p>I use <a class="reference external" href="http://www.quirksmode.org/js/cookies.html">these cookie functions</a> because oddly I can&#8217;t find cookie handling functions in jQuery.  It&#8217;s always weird to me how primitive <tt class="docutils literal"><span class="pre">document.cookie</span></tt> is.  Anyway, CSS looks like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="co1">#flash-message {</span><br />
&nbsp; margin: <span class="nu0">0</span>.5em;<br />
&nbsp; border: 2px solid <span class="co1">#000;</span><br />
&nbsp; background-color: <span class="co1">#9f9;</span><br />
&nbsp; -moz-border-radius: 4px;<br />
&nbsp; text-align: center;<br />
<span class="br0">&#125;</span><br />
<br />
<span class="co1">#flash-message-close {</span><br />
&nbsp; <span class="kw2">float</span>: right;<br />
&nbsp; font-size: <span class="nu0">70</span>%;<br />
&nbsp; margin: 2px;<br />
<span class="br0">&#125;</span><br />
<br />
a<span class="co1">#flash-message-button {</span><br />
&nbsp; text-decoration: none;<br />
&nbsp; color: <span class="co1">#000;</span><br />
&nbsp; border: 1px solid <span class="co1">#9f9;</span><br />
<span class="br0">&#125;</span><br />
<br />
a<span class="co1">#flash-message-button:hover {</span><br />
&nbsp; border: 1px solid <span class="co1">#000;</span><br />
&nbsp; background-color: <span class="co1">#009;</span><br />
&nbsp; color: <span class="co1">#fff;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This doesn&#8217;t have non-Javascript fallback, but I think that&#8217;s okay.  This isn&#8217;t something that a spider would ever see (since spiders shouldn&#8217;t be submitting forms that result in update messages).  Accessible browsers generally implement Javascript so that&#8217;s also not particularly a problem, though there may be additional hints I could give in CSS or Javascript to help make this more readable (if there&#8217;s a message, it should probably be the first thing read on the page).</p>
<p>Another common component of pages that varies separate from the page itself is logged-in status, but that&#8217;s more heavily connected to your application.  Get both into Javascript and you might be able to turn caching way up on a lot of your pages.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/12/17/javascript-status-message-display/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Prism</title>
		<link>http://blog.ianbicking.org/2007/10/25/prism/</link>
		<comments>http://blog.ianbicking.org/2007/10/25/prism/#comments</comments>
		<pubDate>Thu, 25 Oct 2007 23:30:05 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2007/10/25/prism/</guid>
		<description><![CDATA[I&#8217;ve seen talk of MS Silverlight and Adobe AIR. People talk them up like the future of web applications or something. I don&#8217;t know much about them, but I almost completely certain I don&#8217;t want anything to do with them. Here&#8217;s a general rule I have: I don&#8217;t accept anything made by people who hate [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I&#8217;ve seen talk of <a class="reference external" href="http://en.wikipedia.org/wiki/Silverlight">MS Silverlight</a> and <a class="reference external" href="http://en.wikipedia.org/wiki/Adobe_AIR">Adobe AIR</a>.  People talk them up like the future of web applications or something.  I don&#8217;t know <em>much</em> about them, but I almost completely certain I don&#8217;t want anything to do with them.</p>
<p>Here&#8217;s a general rule I have: I don&#8217;t accept anything made by people who hate the web.  If you hate the web and you want to improve the web, I don&#8217;t want anything to do with you.  If you think the web is some kind of <em>implementation detail</em> then I probably don&#8217;t care what you are doing.  If you <em>still</em> think the web is a fad, then you are just nuts; if all you can think of is reasons why the web is stupid and awkward, and you think it&#8217;s some giant step backward (from what?), then you haven&#8217;t thought very deeply about what&#8217;s happened in the world of technology and why.</p>
<p>To me Silverlight and AIR reek of a distaste for the web.</p>
<p>So it is with great delight that I read the <a class="reference external" href="http://labs.mozilla.com/2007/10/prism/">announcement of Mozilla Prism</a>: a bridge between the desktop and the web, written by people who don&#8217;t hate the web.</p>
<p>The premise of Prism from what I can tell is this: to make a web application into a desktop application, you just give the browser a shallowly separate identity.  It lives in its own window, has its own icon, it&#8217;s own launcher.  Maybe runs in its own process for reliability.  You take away the chrome (URL bars, back button, etc).  Unlike previous ideas for Mozilla (like <a class="reference external" href="http://developer.mozilla.org/en/docs/XULRunner">xulrunner</a>) you <em>don&#8217;t</em> add chrome back in with <a class="reference external" href="http://en.wikipedia.org/wiki/XUL">XUL</a>, you just write all the controls with HTML and Javascript.</p>
<p>All the things that Prism <em>isn&#8217;t</em> is what makes it great, because it&#8217;s so damn <em>simple</em>.  The only thing that really seems weird to me is that it is very separate from the browser itself; hopefully this is just temporary, and by the time it&#8217;s really &quot;done&quot; you&#8217;ll be able to just make any page an application directly from Firefox.</p>
<p>This doesn&#8217;t make web applications perfect, of course.  There&#8217;s the offline issue.  There&#8217;s usability issues, like keybindings.  There&#8217;s lots of issues, but all of those issues apply just as much to the web as to a desktop application, and should be solved both places.  Those things can be worked on orthogonally (most interestingly in <a class="reference external" href="http://www.whatwg.org/specs/web-forms/current-work/">Web Forms 2.0</a> and <a class="reference external" href="http://www.whatwg.org/specs/web-apps/current-work/">Web Applications 1.0</a> at <a class="reference external" href="http://www.whatwg.org/">WHAT-WG</a>).  Still, HTML and Javascript <em>right now</em> are totally workable for most applications.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2007/10/25/prism/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Doctest for Ruby</title>
		<link>http://blog.ianbicking.org/2007/08/23/doctest-for-ruby/</link>
		<comments>http://blog.ianbicking.org/2007/08/23/doctest-for-ruby/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 17:10:06 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2007/08/23/doctest-for-ruby/</guid>
		<description><![CDATA[Finally, someone wrote a version of doctest for Ruby. Recently I&#8217;ve been writing most of my tests using stand-alone doctest files. It&#8217;s a great way to do TDD &#8212; mostly because the cognitive load is so low. Also, I write my examples but don&#8217;t write my output, then copy the output after visually confirming it [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Finally, <a class="reference external" href="http://clintonforbes.blogspot.com/2007/08/doctest-for-ruby-and-rails.html">someone wrote a version of doctest for Ruby</a>.</p>
<p>Recently I&#8217;ve been writing most of my tests using <a class="reference external" href="http://python.org/doc/current/lib/doctest-simple-testfile.html">stand-alone doctest files</a>.  It&#8217;s a great way to do TDD &#8212; mostly because the cognitive load is so low.  Also, I write my examples but don&#8217;t write my output, then copy the output after visually confirming it is correct.  So the basic pattern is:</p>
<ul class="simple">
<li>Figure out <em>what</em> I want to do</li>
<li>Figure out <em>how</em> I want to test it</li>
<li>Automate my conditions</li>
<li>Manually inspect whether the output is correct (i.e., implement and debug)</li>
<li>Copy the output so that in the future the manual process is automated (<a class="reference external" href="http://www.cis.upenn.edu/~edloper/projects/doctestmode/">doctest-mode</a> for Emacs makes this particularly easy)</li>
</ul>
<p>The result is a really good balance of manual and automated testing, I think giving you the benefit of both processes &#8212; the ease of manual testing, and the robustness of automated testing.</p>
<p>Another good thing about doctest is it doesn&#8217;t let you hide any boilerplate and setup.  If it&#8217;s easy to use doctest, it&#8217;s probably easy to use the library.</p>
<p>There&#8217;s nothing Python-specific about doctest (e.g., <a class="reference external" href="http://svn.colorstudy.com/doctestjs/trunk/docs/index.html">doctestjs</a>), so it&#8217;s good to see it moving to other languages.  Even if the language doesn&#8217;t have a <a class="reference external" href="http://en.wikipedia.org/wiki/REPL">REPL</a>, IMHO it&#8217;s worth inventing it just for this.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2007/08/23/doctest-for-ruby/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Atompub &amp; OpenID</title>
		<link>http://blog.ianbicking.org/2007/08/06/atompub-openid/</link>
		<comments>http://blog.ianbicking.org/2007/08/06/atompub-openid/#comments</comments>
		<pubDate>Mon, 06 Aug 2007 17:38:58 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2007/08/06/atompub-openid/</guid>
		<description><![CDATA[One of the thinmgs I would like to do is to interact with Atompub (aka Atom Publishing Protocol) stores in Javascript through the browser. Since this effectively the browser itself interacting with the Atompub server, browser-like authentication methods would be nice. But services like Atompub don&#8217;t work nicely with the kinds of authentication methods that [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>One of the thinmgs I would like to do is to interact with <a class="reference external" href="http://atompub.org/rfc4287.html">Atompub (aka Atom Publishing Protocol)</a> stores in Javascript through the browser.  Since this effectively the browser itself interacting with the Atompub server, browser-like authentication methods would be nice.  But services like Atompub don&#8217;t work nicely with the kinds of authentication methods that normal websites use.  One of these is <a class="reference external" href="http://openid.net/">OpenID</a>, which is particularly browser-focused.</p>
<p>From the perspective of a client, OpenID basically works like this:</p>
<ul class="simple">
<li>You need to login.  You tell the original server what your OpenID   URL is, somehow.</li>
<li>The original server does some redirects, maybe some popups, etc.</li>
<li>Your OpenID server (attached to your OpenID URL) authenticates you   in some fashion, and then tells the original server.</li>
<li>The original server probably sets a signed cookie so that in   subsequent requests you stay logged in.  You cannot do this little   redirection dance for every request, since it&#8217;s actually quite   intrusive.</li>
</ul>
<p>So what happens when I have an XMLHttpRequest that needs to be authenticated?  Neither the XMLHttpRequest nor Javascript generally can do the authentication.  Only the browser can, with the user&#8217;s interaction.</p>
<p>One thought I have is a 401 Unauthorized response, with a header like:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
WWW-Authenticate: <span class="kw3">Cookie</span> location=<span class="st0">&quot;http://original.server/login.html&quot;</span><br />
&nbsp;</div>
<p>Which means I need to open up <tt class="docutils literal"><span class="pre">http://original.server/login.html</span></tt> and have the user log in, and the final result is that a cookie will be set.  XMLHttpRequest sends cookies automatically I believe, so once the browser has the cookie then all the Javascript requests get the same cookie and hence authentication.</p>
<p>One problem, though, is that you have to wait around for a while for the login to succede, then continue on your way.  A typical situation is that you have to return to the original page you were requesting, and people often do something like <tt class="docutils literal"><span class="pre">/login?redirect_to=original_url</span></tt>.  In this case we might want something like <tt class="docutils literal"><span class="pre">/login?opener_call=reattempt_request</span></tt>, where when the login process is over we call <tt class="docutils literal"><span class="pre">window.opener.reattempt_request()</span></tt> in Javascript.</p>
<p>Maybe it would make sense for that <tt class="docutils literal"><span class="pre">location</span></tt> variable to be a <a class="reference external" href="http://bitworking.org/projects/URI-Templates/draft-gregorio-uritemplate-01.html">URI Template</a>, with some predefined variables, like opener, back, etc.</p>
<p>For general backward compatibility, would it be reasonable to send 307 Temporary Redirect plus WWW-Authenticate, and let XMLHttpRequests or other service clients sort it out, while normal browser requests do the normal login redirect?</p>
<p><strong>Update:</strong> Another question/thought: is it okay to send multiple WWW-Authenticate headers, to give the client options for how it wants to do authentication?  It seems vaguely okay, according to <a class="reference external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.47">RFC 2616 14.47</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2007/08/06/atompub-openid/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Atom Models</title>
		<link>http://blog.ianbicking.org/2007/08/02/atom-models/</link>
		<comments>http://blog.ianbicking.org/2007/08/02/atom-models/#comments</comments>
		<pubDate>Thu, 02 Aug 2007 16:30:15 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2007/08/02/atom-models/</guid>
		<description><![CDATA[I&#8217;ve been doing a bit more with Atom lately. First, I started writing a library to manipulate Atom feeds and entries. For the moment this is located in atom.py. It uses lxml, as does everything markup related I do these days. I came upon a revelation of sorts when I was writing the library. I [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I&#8217;ve been doing a bit more with Atom lately.</p>
<p>First, I started writing a library to manipulate Atom feeds and entries.  For the moment this is located in <a class="reference external" href="http://svn.colorstudy.com/home/ianb/atom.py">atom.py</a>.  It uses <a class="reference external" href="http://codespeak.net/lxml/">lxml</a>, as does everything markup related I do these days.</p>
<p>I came upon a revelation of sorts when I was writing the library.  I first started with a library that looked like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">class</span> Feed<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, title, ...<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">title</span> = title<br />
&nbsp; &nbsp; &nbsp; &nbsp; ..<br />
&nbsp; &nbsp; @<span class="co1">classmethod</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> parse<span class="br0">&#40;</span>cls, <span class="kw3">xml</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">isinstance</span><span class="br0">&#40;</span><span class="kw3">xml</span>, <span class="kw2">basestring</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">xml</span> = etree.<span class="me1">XML</span><span class="br0">&#40;</span><span class="kw3">xml</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; title = <span class="kw3">xml</span>.<span class="me1">xpath</span><span class="br0">&#40;</span><span class="st0">'//title'</span><span class="br0">&#41;</span>.<span class="me1">text</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> cls<span class="br0">&#40;</span>title, ...<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> serialize<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; el = etree.<span class="me1">Element</span><span class="br0">&#40;</span><span class="st0">'{%s}feed'</span> % atom_ns<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; title = etree.<span class="me1">Element</span><span class="br0">&#40;</span><span class="st0">'{%s}title'</span> % atom_ns<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; title.<span class="me1">text</span> = <span class="kw2">self</span>.<span class="me1">title</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; el.<span class="me1">append</span><span class="br0">&#40;</span>title<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> el<br />
&nbsp;</div>
<p>Obviously there&#8217;s ways to improve this and make it less verbose, and I went down that path for a while.  But then I decided the whole path was wrong.  Atom <em>is</em> XML.  It&#8217;s not the representation of some object I&#8217;m creating.  If I have something that can&#8217;t be represented in XML, it isn&#8217;t Atom, and it doesn&#8217;t belong in my Atom-related objects.</p>
<p>So instead I started making lxml more convenient when using Atom.  I don&#8217;t keep any information except what is in the markup, I just make it more convenient to access that information.</p>
<p>I used lots of <a class="reference external" href="http://users.rcn.com/python/download/Descriptor.htm">descriptors</a> to do this, as the same patterns happened over and over.  For instance, the Feed object is fairly simple:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">class</span> Feed<span class="br0">&#40;</span>AtomElement<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; entries = _findall_property<span class="br0">&#40;</span><span class="st0">'entry'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; author = _element_property<span class="br0">&#40;</span><span class="st0">'author'</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Which basically means that <tt class="docutils literal"><span class="pre">feed.entries</span></tt> returns all <tt class="docutils literal"><span class="pre">&lt;entry&gt;</span></tt> elements, and <tt class="docutils literal"><span class="pre">feed.author</span></tt> returns the single <tt class="docutils literal"><span class="pre">author</span></tt> element.</p>
<p>There&#8217;s also accessors for text elements (like <tt class="docutils literal"><span class="pre">&lt;id&gt;</span></tt>) and date containing elements (like <tt class="docutils literal"><span class="pre">&lt;updated&gt;</span></tt>) and just to access XML attributes as Python attributes.</p>
<p>There&#8217;s a number of advantages:</p>
<ul class="simple">
<li>No hidden state.</li>
<li>No deferred errors, since everything is always represented in the   <a class="reference external" href="http://en.wikipedia.org/wiki/XML_Information_Set">XML infoset</a>.</li>
<li>All XML extensions work, even though my classes don&#8217;t know anything   in particular about them.  There&#8217;s a full API for manipulating the   XML that you can use, you don&#8217;t have to use my APIs.</li>
<li>Even more obscure kinds of extensions work fine, like a custom attribute on an element.  There&#8217;s absolutely zero normalization that happens.</li>
<li>I only have to write the parts where the normal XML (lxml) APIs are inconvenient, so the implementation stays simple.</li>
<li>There&#8217;s no confusion over which object I might be talking about in my code.  There&#8217;s no distinction between the XML object and the domain object.</li>
</ul>
<p>Since then I&#8217;ve been working on a <a class="reference external" href="https://svn.openplans.org/svn/TaggerClient/trunk/javascript/atom.js">Javascript library</a> for handling Atom.  It&#8217;s not as elegant.  I am trying to keep to this same principle, but of course I can&#8217;t actually extend the DOM and so I can&#8217;t add convenience methods.  So instead I&#8217;m making a class that lightly wraps the DOM objects, with explicit getters and setters that simply read and modify those DOM objects.</p>
<p>One thing that I have found very useful in my development on the Javascript side is doctest-style testing.  You can see the <a class="reference external" href="https://svn.openplans.org/svn/TaggerClient/trunk/javascript/tests/test.html">test</a>, but to run it you have to check it out (it uses some <tt class="docutils literal"><span class="pre">svn:externals</span></tt> which you don&#8217;t get through the direct svn access).  After using that testing some more and being pleased with the result, I decided to package the Javascript doctest runner a bit better.  I removed the framework dependencies, did a bit of renaming (now it is <em>doctestjs</em> or <tt class="docutils literal"><span class="pre">doctest.js</span></tt> instead of <em>jsdoctest</em>), wrote up <a class="reference external" href="http://svn.colorstudy.com/doctestjs/trunk/docs/index.html">fairly comprehensive docs</a>, and uploaded it to <a class="reference external" href="http://openjsan.org/doc/i/ia/ianb/doctestjs/0.9/">JSAN</a> (though at the moment the trunk from svn is probably better to use).  I think it&#8217;s an excellent way of doing unit testing in Javascript, much better than any of the alternatives I&#8217;ve seen.  It even has some notable advantages over <a class="reference external" href="http://python.org/doc/current/lib/module-doctest.html">Python&#8217;s doctest</a>, like if you are using <a class="reference external" href="http://www.getfirebug.com/">Firebug</a> (which you must if you do Javascript development) you get a console session that runs in the same namespace as your tests, so you can easily do inspection of the objects if there&#8217;s a failure.</p>
<p>I&#8217;m not sure about JSAN.  It&#8217;s nice to have an index.  But I think they copy stuff from CPAN a bit too much.  Why should you have a text README file?  That&#8217;s just silly; of course Javascript documentation should be HTML.  They batch processing.  Processing one package a day<br />
on the fly shouldn&#8217;t be overwhelming.  They want a MANIFEST file.  The standard metadata file is YAML, not JSON.  This should all be a little more Javascripty in my opinion.  But they also accept any kind of upload, so there&#8217;s nothing stopping you from ignoring what you don&#8217;t<br />
care about.  I&#8217;ll probably improve the packaging of doctestjs a bit in the future, and still ignore the parts I think are silly.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2007/08/02/atom-models/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.675 seconds -->

