Youth culture killed my dog http://www.papermountain.org/blog/index.cgi Constantly one step behind the next big thing en-us Poor Man's Ajax http://www.papermountain.org/blog/index.cgi/Tech/Javascript/PoorMansAjax.txl <p>Last summer I began working on extending <a href="http://www.cincomsmalltalk.com/userblogs/avi/View.ssp">Avi Bryant&#8217;s</a> <a href="http://www.cincomsmalltalk.com/userblogs/avi/blogView?showComments=true&amp;entry=3268075684">liveUpdater.js</a> and integrating it into <a href="http://borges.rubyforge.org/">Borges</a> . I was successful as far as that went and reported my results <a href="http://www.papermountain.org/blog/index.cgi/Tech/Ruby/BorgesDHTML.rdoc">here</a> and <a href="http://www.papermountain.org/blog/index.cgi/Tech/Ruby/AutoCompleteXMLHttpRequest.txl">here</a> . Unfortunately Borges turned out to be a dead end because of some fundamental problems with its implementation.</p> <p>However <a href="http://cvs.sourceforge.net/viewcvs.py/lakeshore/lakeshore/resources/liveUpdater.js?view=markup">my fork of liveUpdater.js</a> has went on to lead a productive part in the <a href="http://lakeshore.sourceforge.net">Lakeshore</a> project (more about it later). liveUpdater has been a core piece of the user interface for many commercial applications written by myself, the gentle folk at <a href="http://www.missiondata.com/">Mission Data</a> , and several other people that are using Lakeshore. So in short, liveUpdater is under active development and is being used successfully in several commercial applications.</p> <p>Enough with the history lesson&#8230; take a look at the <a href="http://www.papermountain.org/demos/live/">demo</a> . What&#8217;s happening is that some event on the client side (a keypress, a click, etc) triggers a request to the server via XMLHttpRequest. The server returns one or more snippets of <span class="caps">HTML</span>. The snippets replace existing sections of the current document based on their &#8220;id&#8221;. Very nice things are now possible with only a tiny amount (or in the case of Lakeshore, no) javascript coding. You get the dynamic feel and most of the responsiveness that is promised by <a href="http://www.adaptivepath.com/publications/essays/archives/000385.php">Ajax</a> without splitting your logic between the client and the server.</p> <p>Here is how the &#8220;Update time&#8221; link on the <a href="http://www.papermountain.org/demos/live/">demo</a> works. The <span class="caps">HTML</span> contains an empty div with an id of &#8220;time&#8221;. The &#8220;Update time&#8221; link is set to use liveUpdater with a target <span class="caps">URL</span> of <a href="http://www.papermountain.org/demos/live/live-demos-source.html">time.cgi</a> :<br /> <pre><br /> document.getElementById(&#8216;time-link&#8217;).onclick = liveUpdaterUri(&#8216;time-link&#8217;,&#8216;time.cgi&#8217;)<br /> </pre></p> <p>time.cgi sets the content type of its response to &#8220;text/xml&#8221;. It returns a body element containing a div with the current time. Note that the id of the div matches the id of the empty div in the original <span class="caps">HTML</span> document. If you wished to replace additional elements on the page just include them in the body element.</p> Javascript, it's what's for dinner http://www.papermountain.org/blog/index.cgi/Tech/Javascript/JavascriptForDinner.txl <p>Javascript is a good language. I like Ruby better, but it is certainly better than Java (which is not a good language) and it has has certain unique charms. A dynamic, prototyped OO language with a runtime penetration of nearly 100% on desktop systems. I&#8217;m ashamed I haven&#8217;t done more with it. <br /> This <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/117184">script</a> from Florian Gross that adds several of the Ruby standard methods to Javascript is an excellent example how flexible and clean Javascript is. Below is a code snippit for adding Ruby style mixin support to Javascript. While it is impressive that Javascript is flexible enough to allow this sort of thing, the truly amazing bit is that it is seven lines of straightforward code that even a casual Javascripter such as myself can understand.</p> <pre> Object.prototype.extend = function(other) { if (!this.mixins) this.mixins = [] this.mixins.push(other) for (var property in other) if (!this.hasOwnProperty(property)) this[property] = other[property] } </pre> <p>Now for the practical aspects of programming Javascript Ruby style.<br /> Here&#8217;s some brief <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/117188">documentation</a> written by Florian. Also while using ruby.js in a script that interacts with the <span class="caps">DOM</span>, I ran into a bit of trouble. In Firefox at least the <code>Array</code> that is returned by <code>getElementsByTagName</code> does not have the added methods. I would appreciate any explanation as to why this is so, but there is a work around in the mean time.<br /> Instead of:<br /> <pre><br /> foo.getElementsByTagName(&#8216;tr&#8217;).each(function(row) {<br /> &#8230;do something with the row&#8230;<br /> });<br /> </pre><br /> You have to:<br /> <pre><br /> Array.fromObject(foo.getElementsByTagName(&#8216;tr&#8217;)).each(function(row) {<br /> &#8230;do something with the row&#8230;<br /> });<br /> </pre></p>