<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Jay by Jay Fresh &#187; javascript</title>
	<atom:link href="http://jaybyjayfresh.com/category/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://jaybyjayfresh.com</link>
	<description>Right-on slack-jawed yokel-type tech-farmer</description>
	<lastBuildDate>Wed, 01 Feb 2012 08:45:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jaybyjayfresh.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Jay by Jay Fresh &#187; javascript</title>
		<link>http://jaybyjayfresh.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jaybyjayfresh.com/osd.xml" title="Jay by Jay Fresh" />
	<atom:link rel='hub' href='http://jaybyjayfresh.com/?pushpress=hub'/>
		<item>
		<title>International JavaScript show &#8216;n&#8217; tell @ Async</title>
		<link>http://jaybyjayfresh.com/2010/11/11/international-asnyc-javascript-meetup/</link>
		<comments>http://jaybyjayfresh.com/2010/11/11/international-asnyc-javascript-meetup/#comments</comments>
		<pubDate>Thu, 11 Nov 2010 21:46:05 +0000</pubDate>
		<dc:creator>Jonathan Lister</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[asyncjs]]></category>
		<category><![CDATA[brighton]]></category>
		<category><![CDATA[fullfrontal]]></category>
		<category><![CDATA[fullfrontalconf]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[theskiff]]></category>

		<guid isPermaLink="false">http://jaybyjayfresh.com/?p=839</guid>
		<description><![CDATA[The Full Frontal JavaScript conference is tomorrow, so this is a very international audience. A bit of a show &#8216;n&#8217; tell tonight at the fortnightly Async JavaScript meetup, hosted at The Skiff in Brighton&#8230; notes below. Links for the talks ought to be added to the Async blog post (http://asyncjs.com/showntell3/) by the speakers. The next [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=839&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://2010.full-frontal.org" target="_blank">Full Frontal</a> JavaScript conference is tomorrow, so this is a very international audience.</p>
<p>A bit of a show &#8216;n&#8217; tell tonight at the fortnightly Async JavaScript meetup, hosted at The Skiff in Brighton&#8230; notes below.</p>
<p>Links for the talks ought to be added to the Async blog post (http://asyncjs.com/showntell3/) by the speakers.</p>
<p>The next Async features Kyran Dale (session 7 below) on module loading (&#8216;requireJS&#8217;), in two weeks time, also @ The Skiff.</p>
<h3>1. Mike de Boer (from ajax.org) &#8211; Cloud9 IDE</h3>
<p>Written in JS (as a node app) for dev&#8217;ing JS. Nice. &#8220;npm install cloud9&#8243;</p>
<p>Mounts filesystem/WebDAV server.</p>
<p>You can write a node app, which is run as a separate app and has the output logged to a console. They&#8217;ll have an online version up soon.</p>
<p>Does live debugging, and you can variables real-time via breakpoints. You can also edit the code when execution is paused. i.e. hot-code swapping. He mentioned node inspector (what&#8217;s that?).</p>
<p>The code editor can cope with 134k lines of code. Which textmate can&#8217;t. Nice.</p>
<p>You get a command-line too, for using git (other version control systems coming later).</p>
<p>http://github.com/ajaxorg</p>
<h3>2. Glenn Jones (Madgex) &#8211; Draggables</h3>
<p>HTML5 experiment for dragging data between systems.</p>
<p>Lets you drag across browsers, which is cool. Also you can drag html files (and zipped html files!).</p>
<p>Really nice little thing with a bookmarklet injecting a draggable icon into a page (well, on Firefox).</p>
<p>Glenn is also working on a microformats parser that works cross-browser, which he will open-source.</p>
<h3>3. Phil Hawksworth (The Team) &#8211; nodejs &amp; ndistro &#8211; &#8220;multiple projects. quickly.&#8221;</h3>
<p>I.e. how Phil works.</p>
<p>Problem with node is deployment (i.e. build) can be hard. Plus, the codebase is changing frequently. So how to cope?</p>
<p>ndistro &#8211; a node distribution toolkit (github.com/visionmedia/ndistro)</p>
<p>Note: installing involves running install script as root (sudo su Phil recommends)</p>
<p>You write ndistro files for each project, where you specify the version of node and any modules from github</p>
<p>Phil like ejs as a templating language</p>
<p>Phil has some very nice presentation techniques &#8211; videos of terminals and a funny, eased, scrolling of a webpage. Guess keynote == good?</p>
<p>Seeing as ndistro files are just bash scripts, you can nest another running of ndistro inside the ndistro file</p>
<p>expressjs = &#8220;almost&#8221; MVC for node</p>
<p>After a Q: Not sure if npm would play nicely with this.</p>
<h3>4. Prem (@premasagar) &amp; Graeme Sutherland (@grasuth) &#8211; Sqwidget</h3>
<p>http://github.com/premasagar/sqwidget</p>
<p>The problem: widget developers have a really big problem developing something that runs in other people&#8217;s environments (which is like cross-browser development, but worse).</p>
<p>One solution: iFrame</p>
<p>Their solution: sqwidget.</p>
<p>It sandboxes CSS and JavaScript. This is cool, because you can do things like lightboxes, which you can&#8217;t do with iFramed widgets.</p>
<p>The widget is embedded using a DIV and its data attributes to do settings</p>
<p>Q: option to swap in different templating? A: yes. Built-in one is a hand-built library called Tim.</p>
<p>Q: licence? A: MIT</p>
<h3>5. Mark Wubben, from Copenhagen (who needs a place to live in London) &#8211; Chrome2iPad</h3>
<p>Problem: how do I get my tabs I have open in Chrome into my iPad?</p>
<p>Solution: Chrome2iPad.</p>
<p>There is a Chrome extension using Socket.io (a node module) which hotlinks to a webpage on the iPad to the Chrome browser via a Chrome extension</p>
<p>Not released on github yet. When it is available, it will be on http://github.com/novemberborn</p>
<h3>6. Paul Downey (@psd, Osmosoft) &#8211; TiddlySpace</h3>
<p>TiddlyWiki is a single-page HTML app.</p>
<p>I&#8217;m writing these notes in a TiddlyWiki&#8230;</p>
<p>TiddlyWiki is interesting because it can save itself when on a file URI.</p>
<p>All the plugins are written in JavaScript.</p>
<p>TiddlySpace is like TiddlyWikis in the sky. It&#8217;s slightly different from file-based TiddlyWikis, since you can follow people.</p>
<p>TiddlySpace is based on TiddlyWeb, which is an open-source hosting platform for tiddlers, with a RESTful API.</p>
<p>A tiddler in a TiddlyWiki is a div; a tiddler on TiddlySpace can be HTML, JavaScript, SVG &#8211; anything.</p>
<h3>7. Kyran Dale (academia) &#8211; JavaScript physics</h3>
<p>Impressed by JavaScript&#8217;s performance to do simulations.</p>
<p>Shows Craig Reynold&#8217;s Boids running 300 objects, drawn in canvas. Chrome on Linux. Real-time variable changing.</p>
<p>Now a robotics demo &#8211; 100 robots (Brightenbergs) with light-sensors and lights. They go mad. But without slow-down.</p>
<p>Next a magnetic controller. This one does some weird stuff, but again, in a peformant way.</p>
<p>Q: source? A: will be available, probably on a Mercurial repo (http://bitbucket.com/keirandale)</p>
<h3>8. Morgan Roderick (@mrgnrdrck) &#8211; PubSub in JavaScript</h3>
<p>Writes really large systems in JavaScript.</p>
<p>PubSub is messaging in JavaScript. It is an alternative to the &#8220;observer pattern&#8221; (see Java, apparently).</p>
<p>Keeps different bits of your system nicely decoupled.</p>
<p>Don&#8217;t use PubSub when you have 1:1 communication, or need accurate control.</p>
<p>http://github.com/mroderick/pubsubjs</p>
<p>Q: is is threaded? A: all messages are passed asynchronously. In terms of performance, it&#8217;s about 10x faster than jQuery.</p>
<p>Q: how is it different to custom events in jQuery? A: it doesn&#8217;t depend on the DOM</p>
<p>Q: how do you wake listeners up? A: They just get called. If a call fails, the exception is caught and it is called again.﻿</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/839/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/839/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/839/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/839/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/839/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/839/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/839/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/839/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=839&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2010/11/11/international-asnyc-javascript-meetup/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ddf442971aebf6ce72763d02ead1c832?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
		<item>
		<title>JavaScript in the cloud</title>
		<link>http://jaybyjayfresh.com/2010/05/04/javascript-in-the-cloud/</link>
		<comments>http://jaybyjayfresh.com/2010/05/04/javascript-in-the-cloud/#comments</comments>
		<pubDate>Tue, 04 May 2010 20:41:11 +0000</pubDate>
		<dc:creator>Jonathan Lister</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[appjet]]></category>
		<category><![CDATA[coda]]></category>
		<category><![CDATA[commonjs]]></category>
		<category><![CDATA[elusivehippo]]></category>
		<category><![CDATA[env.js]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[jaxer]]></category>
		<category><![CDATA[joyent]]></category>
		<category><![CDATA[jsdom]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[PAAS]]></category>
		<category><![CDATA[platform as a service]]></category>
		<category><![CDATA[reasonably smart]]></category>
		<category><![CDATA[ryan dahl]]></category>
		<category><![CDATA[server-side javascript]]></category>
		<category><![CDATA[smart platform]]></category>
		<category><![CDATA[smartplatform]]></category>
		<category><![CDATA[ssjs]]></category>

		<guid isPermaLink="false">http://jaybyjayfresh.com/?p=811</guid>
		<description><![CDATA[The idea of running JavaScript on the server has been around for a while now (think Jaxer back in 2008), but it recently got a big boost with the featuring of Node.js at JSConf in November 2009. Node.js found immediate fame by demonstrating blinding performance as a web server, and by building on the hotly hyped V8 JavaScript engine Google bundled [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=811&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignright" style="width: 250px"></p>
<div class="mceTemp" style="text-align:auto;"><a href="http://www.flickr.com/photos/flowerhouse/4384979280/"><img class=" " title="The ambassador's reception..." src="http://farm5.static.flickr.com/4004/4384979280_1da22ec8da_m.jpg" alt="" width="240" height="240" /></a></div>
<p><p class="wp-caption-text">thanks to flowerhouse on flickr</p></div>
<p>The idea of running JavaScript on the server has been around for a while now (think <a title="John Resig discovers Jaxer" href="http://ejohn.org/blog/server-side-javascript-with-jaxer/" target="_blank">Jaxer</a> back in 2008), but it recently got a big boost with the featuring of <a title="Node.js" href="http://nodejs.org" target="_blank">Node.js</a> at <a title="Ryan Dahl presents Node.js at JSConf 2009" href="http://jsconf.eu/2009/video_nodejs_by_ryan_dahl.html" target="_blank">JSConf</a> in November 2009. Node.js found immediate fame by demonstrating blinding performance as a web server, and by building on the hotly hyped V8 JavaScript engine Google bundled with Chrome.</p>
<p>I have a big interest in server-side JavaScript (SSJS) because I generally code in the browser and would enjoy being able to make things happen on a server without having to resort to another language. The ideal would be to take client-side code and run it unchanged on a server. The last step is pain-free application hosting &#8211; call it &#8220;<a title="Platform as a service on Wikipedia.org" href="http://en.wikipedia.org/wiki/Platform_as_a_service" target="_blank">Platform as a service</a>&#8221; for want of a less boring name.</p>
<p>Over a year ago, Joyent <a title="Joyent blog announcement of Reasonably Smart acquisition" href="http://www.joyent.com/joyeurblog/2009/01/14/joyent-acquires-reasonably-smart/" target="_blank">bought</a> Reasonably Smart, a cloud provider of SSJS, and subsequently transmuted it into <a title="Joyent Smart Platform" href="http://smart.joyent.com/" target="_blank">Smart Platform</a>, which runs on their distributed infrastructure. This followed the shining example of Heroku and Google App Engine, in that application deployment became a matter of pushing some new code to a Git repository online. For me, this was fantastically attractive, as I avoid touching servers as much as realistically possible. They came out with Smart Platform shortly before <a title="Me writing about AppJet doing the bad thing by closing" href="http://jaybyjayfresh.com/2009/06/02/appjet-make-boo-boo-they-closed/" target="_blank">the demise of AppJet&#8217;s free service</a>, which I had been happily trying for a while, as it did much the same thing.</p>
<p>Nearly a year on, and Smart Platform hasn&#8217;t really taken off, if <a title="Smart Platform search on Google Trends" href="http://www.google.com/trends?q=%22smart+platform%22&amp;ctab=0&amp;geo=all&amp;date=all" target="_blank">Google Trends</a> is anything to go by. And my ambitions to run my entire web estate on identical server-side and client-side code have rather fallen by the way-side. I am happy to see that Smart Platform now has a permanent full-time coder (<a title="@konobi on Twitter" href="http://twitter.com/konobi" target="_blank">@konobi</a>), who is making Smart Platform play nicely with the <a title="CommonJS is a movement to improve the JavaScript language through agreeing standards" href="http://commonjs.org/" target="_blank">CommonJS spec</a> for server-side JS, but I don&#8217;t yet know when Joyent are going to drop a new release, or where they&#8217;re going with it.</p>
<p>Enter Node.js. The interest in Node.js has <a title="Node.js on Google Trends" href="http://www.google.com/trends?q=node.js&amp;ctab=0&amp;geo=all&amp;date=all" target="_blank">stayed high</a> since its November launch, with developers building an <a title="Projects / Applications using Node.js" href="http://wiki.github.com/ry/node/" target="_blank">assortment of frameworks and tools</a> on top of it or with it, in effect legitimising it as a serious development environment for software running on a server.</p>
<p>Of significant interest to me is the <a title="tmpvar's jsdom on GitHub" href="http://github.com/tmpvar/jsdom" target="_blank">jsdom</a> project, which brings the browser environment to Node.js in a similar way to how <a title="Env.js brings the browser model to the server" href="http://env-js.appspot.com/" target="_blank">Env.js</a> brought it to Rhino (<a title="Env.js port to Ruby" href="http://github.com/smparkes/env-js" target="_blank">and Ruby</a>). Env.js has supported jQuery <a title="First announcement of Env.js on John Resig's blog" href="http://ejohn.org/blog/bringing-the-browser-to-the-server/" target="_blank">since the get-go</a>, and there are <a title="Can I use jQuery with Node.js? - StackOverflow" href="http://stackoverflow.com/questions/1801160/can-i-use-jquery-with-node-js" target="_blank">rumblings</a> of jQuery support in Node.js via jsdom. Both these situations inspire joy as, if they pan out successfully, I&#8217;ll be able to use one methodology for writing and testing JavaScript applications, whether they run in the browser or on the server. Unfortunately, I&#8217;ve not seen Env.js working on any hosted platform (although Smart Platform <a title="Smart Platform and Env.js / jQuery on Env.js Google Group" href="http://groups.google.com/group/envjs/browse_thread/thread/f42f48a515852fcc" target="_blank">may get it soon</a>).</p>
<p>The number of cloud providers for Node.js has increased from 0 to 2 very recently: Heroku has <a title="Heroku announce experimental Node.js support" href="http://blog.heroku.com/archives/2010/4/28/node_js_support_experimental/" target="_blank">announced</a> a very experimental Node.js stack, and <a title="ElusiveHippo Node.js hosting" href="http://elusivehippo.com">ElusiveHippo</a> is in development, releasing accounts slowly. I should probably also mention that Ryan Dahl (who created Node.js) works for Joyent, so I wouldn&#8217;t be suprised if a Smart Platform-style service came out for Node.js.</p>
<p>Now then, if Coda starts <a title="Are you using Coda and Git? - Get Satisfaction" href="http://getsatisfaction.com/panic/topics/are_you_using_coda_and_git" target="_blank">supporting Git</a>, or I start doing all my code editing in Bespin, I think with a bit of fairy-dust I&#8217;m going to have a pretty slick JavaScript-only setup fairly soon&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/811/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/811/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/811/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=811&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2010/05/04/javascript-in-the-cloud/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ddf442971aebf6ce72763d02ead1c832?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>

		<media:content url="http://farm5.static.flickr.com/4004/4384979280_1da22ec8da_m.jpg" medium="image">
			<media:title type="html">The ambassador&#039;s reception...</media:title>
		</media:content>
	</item>
		<item>
		<title>Testing Adobe AIR applications with QUnit</title>
		<link>http://jaybyjayfresh.com/2009/11/04/testing-adobe-air-applications-with-qunit/</link>
		<comments>http://jaybyjayfresh.com/2009/11/04/testing-adobe-air-applications-with-qunit/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 17:29:17 +0000</pubDate>
		<dc:creator>Jonathan Lister</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[adobe air]]></category>
		<category><![CDATA[adobeair]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[qunit]]></category>
		<category><![CDATA[web standards]]></category>
		<category><![CDATA[webstandards]]></category>

		<guid isPermaLink="false">http://jaybyjayfresh.com/?p=778</guid>
		<description><![CDATA[I&#8217;d like to say I always write tests before I write any JavaScript code&#8230; Those times when I do write tests, I use the QUnit framework, which is used to test jQuery, so pretty well-tested itself. I&#8217;ve recently been putting together an Adobe AIR application using HTML, CSS and JavaScript (aka Web Standards), which is [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=778&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d like to say I always write tests before I write any JavaScript code&#8230; Those times when I do write tests, I use the <a title="QUnit documentation on jQuery site" href="http://docs.jquery.com/QUnit" target="_blank">QUnit</a> framework, which is used to test <a title="The write less, do more JavaScript library" href="http://jquery.com" target="_blank">jQuery</a>, so pretty well-tested itself.</p>
<p>I&#8217;ve recently been putting together an <a title="Adobe's toolkit for Rich Internet Applications in the browser and on the desktop" href="http://www.adobe.com/products/air" target="_blank">Adobe AIR</a> application using HTML, CSS and JavaScript (aka <a title="The Web Standards Project" href="http://www.webstandards.org/" target="_blank">Web Standards</a>), which is very empowering and everything, but turned out to be a little tricky to write tests for. All the interesting stuff I wanted to do through AIR&#8217;s <code>window.runtime</code> object, such as opening native windows and messing with dock icons, is missing from the browser if you&#8217;re trying to test the JavaScript components in isolation. The ideal would be able to run your QUnit tests within the AIR runtime itself.</p>
<p>Fortunately, it&#8217;s straightforward to create a test app that wraps the QUnit test runner in the AIR runtime and exercises your code. Here&#8217;s how I got going:</p>
<h2>Setting up the file structure</h2>
<p>The folder structure I am using for the AIR app is like this:</p>
<p><pre class="brush: xml;">
/myApp
   myApp.html
   myApp-app.xml
   /js
      myApp.js
   /css
      styles.css
</pre></p>
<p>The <code>myApp-app.xml</code> file is the &#8220;application descriptor&#8221; that AIR uses to create the <code>.air</code> package when you build the app.</p>
<p>I added two folders at the same level as <code>/myApp</code>, to contain the test framework and test code; the complete structure looks like:</p>
<p><pre class="brush: xml;">
/myApp
   myApp.html
   myApp-app.xml
   /js
      myApp.js
      AIRAliases.js
      jquery-1.3.2.min.js
   /css
      styles.css

/myAppTests
   runner.html
   tests.js
   myAppTests-app.xml

/qunit
   testrunner.js
   testsuite.css
</pre></p>
<h2>Configuring the test app</h2>
<p>The application descriptor for myAppTests is not very different from the descriptor for myApp; here they are:</p>
<p><pre class="brush: xml;">
myApp-app.xml:
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;application xmlns=&quot;http://ns.adobe.com/air/application/1.5&quot;&gt;
    &lt;id&gt;examples.html.myApp&lt;/id&gt;
    &lt;version&gt;0.1&lt;/version&gt;
    &lt;filename&gt;myApp&lt;/filename&gt;
    &lt;initialWindow&gt;
        &lt;content&gt;myApp.html&lt;/content&gt;
        &lt;visible&gt;true&lt;/visible&gt;
        &lt;width&gt;400&lt;/width&gt;
        &lt;height&gt;800&lt;/height&gt;
    &lt;/initialWindow&gt;
&lt;/application&gt;

myAppTests-app.xml:
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;application xmlns=&quot;http://ns.adobe.com/air/application/1.5&quot;&gt;
    &lt;id&gt;examples.html.myAppTests&lt;/id&gt;
    &lt;version&gt;0.1&lt;/version&gt;
    &lt;filename&gt;myAppTests&lt;/filename&gt;
    &lt;initialWindow&gt;
        &lt;content&gt;myAppTests/runner.html&lt;/content&gt;
        &lt;visible&gt;true&lt;/visible&gt;
        &lt;width&gt;400&lt;/width&gt;
        &lt;height&gt;800&lt;/height&gt;
    &lt;/initialWindow&gt;
&lt;/application&gt;
</pre></p>
<p>The main structural difference is that <code>myApp-app.xml</code> has an <code>initialWindow.content</code> property set to <code>myApp.html</code>, whereas <code>myAppTests-app.xml</code> refers to the test runner from a directory above: <code>myAppTests/runner.html</code>. This is needed because the test app needs to have its working directory set to the top-level of the file structure, otherwise <code>runner.html</code> won&#8217;t be able to get at all the files it needs in other directories (more below).</p>
<h2>Putting the correct files in runner.html</h2>
<p>Here&#8217;s a <code>runner.html</code> that works with the folder structure described above:</p>
<p><pre class="brush: xml;">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt;
&lt;html lang=&quot;en&quot;&gt;
	&lt;head&gt;
		&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
		&lt;title&gt;Test Suite&lt;/title&gt;
		&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;../qunit/testsuite.css&quot;&gt;
		&lt;script src=&quot;../myApp/js/AIRAliases.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
		&lt;script src=&quot;../myApp/js/jquery-1.3.2.min.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
		&lt;script src=&quot;../qunit/testrunner.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
		&lt;script src=&quot;../myApp/js/myApp.js&quot;&gt;&lt;/script&gt;
		&lt;script src=&quot;tests.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;h2 id=&quot;banner&quot;&gt;&lt;/h2&gt;
		&lt;h2 id=&quot;userAgent&quot;&gt;&lt;/h2&gt;
		&lt;ol id=&quot;tests&quot;&gt;&lt;/ol&gt;
		&lt;div id=&quot;main&quot;&gt;&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;</pre></p>
<h2>Running the test suite in debug mode</h2>
<p>The easiest way to run the test suite is to use the built-in Adobe Debugger, which lets you test your app without having to build it into an AIR package:</p>
<p><pre class="brush: plain;">
adl myAppTests/myAppTests-app.xml .
</pre></p>
<p>Don&#8217;t forget the &#8216;.&#8217; character on the end &#8211; this tells the debugger to run with the top-level directory as the working directory &#8211; without it, the default is the same directory as XML file.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/778/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/778/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/778/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/778/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/778/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/778/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/778/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/778/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=778&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2009/11/04/testing-adobe-air-applications-with-qunit/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ddf442971aebf6ce72763d02ead1c832?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
		<item>
		<title>Online banking with JavaScript &#8211; first working thing</title>
		<link>http://jaybyjayfresh.com/2009/08/06/online-banking-with-javascript-first-working-thing/</link>
		<comments>http://jaybyjayfresh.com/2009/08/06/online-banking-with-javascript-first-working-thing/#comments</comments>
		<pubDate>Thu, 06 Aug 2009 22:49:55 +0000</pubDate>
		<dc:creator>Jonathan Lister</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[mashups]]></category>
		<category><![CDATA[screenscraping]]></category>

		<guid isPermaLink="false">http://jaybyjayfresh.com/?p=714</guid>
		<description><![CDATA[I recorded this at Islington Hackspace tonight, figured it would be cool to share visually rather than have a big blag-rant, (see my last post for one of those). It ought to be self-explanatory. I&#8217;m thinking about wrapping this up in an iPhone app so I can pay people for free. Rather than use PayPal [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=714&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I recorded this at Islington <a title="London Hackspace" href="http://london.hackspace.org.uk/" target="_blank">Hackspace</a> tonight, figured it would be cool to share visually rather than have a big blag-rant, (see <a title="How to build a DIY TwitPic without any coding skillz" href="http://jaybyjayfresh.com/2009/07/30/how-to-build-a-diy-twitpic-without-any-coding-skillz/" target="_blank">my last post</a> for one of those).</p>
<p>It ought to be self-explanatory. I&#8217;m thinking about wrapping this up in an iPhone app so I can pay people for free. Rather than use PayPal or something.</p>
<p>Sorry it&#8217;s a bit blurry.</p>
<div class='embed-vimeo' style='text-align:center;'><iframe src='http://player.vimeo.com/video/5986056' width='400' height='300' frameborder='0'></iframe></div>
<p><a title="HSBC ScreenScraper source on GitHub" href="http://github.com/jayfresh/HSBC-ScreenScraper/tree/master" target="_blank">Source</a> (hopefully changing lots) on github.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/714/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/714/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/714/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/714/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/714/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/714/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/714/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/714/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=714&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2009/08/06/online-banking-with-javascript-first-working-thing/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ddf442971aebf6ce72763d02ead1c832?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
		<item>
		<title>Notes on migrating an application from AppJet to Smart Platform</title>
		<link>http://jaybyjayfresh.com/2009/07/16/notes-on-migrating-an-application-from-appjet-to-smart-platform/</link>
		<comments>http://jaybyjayfresh.com/2009/07/16/notes-on-migrating-an-application-from-appjet-to-smart-platform/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 16:53:42 +0000</pubDate>
		<dc:creator>Jonathan Lister</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[appjet]]></category>
		<category><![CDATA[joyent]]></category>
		<category><![CDATA[server-side javascript]]></category>
		<category><![CDATA[serversidejavascript]]></category>
		<category><![CDATA[smart platform]]></category>
		<category><![CDATA[smartplatform]]></category>
		<category><![CDATA[ssjs]]></category>

		<guid isPermaLink="false">http://jaybyjayfresh.com/?p=691</guid>
		<description><![CDATA[I&#8217;ve been wingeing quite a lot recently about AppJet&#8217;s demise and the shoddy state of potential replacements, and got quite a nice response from Jim Pick at Joyent. I decided today to have a play with their new Smart Platform and had a go at porting one of my AppJet applications over to Smart. Here&#8217;s [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=691&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been wingeing quite a lot recently about AppJet&#8217;s demise and the shoddy state of potential replacements, and got quite a <a title="Jim comments on my chat about Joyent" href="http://jaybyjayfresh.com/2009/07/06/joyent-smart-platform-a-replacement-for-appjet/#comment-2813" target="_blank">nice response</a> from Jim Pick at Joyent. I decided today to have a play with their new Smart Platform and had a go at porting one of my AppJet applications over to Smart. Here&#8217;s my notes, fresh from the lab&#8230;</p>
<blockquote><p>It&#8217;s not as simple as hitting an edit button yet, but it&#8217;s still worth having a play. The use of <a title="Sammy micro-framework for JavaScript web apps" href="http://code.quirkey.com/sammy" target="_blank">Sammy</a> to handle and dispatch incoming requests, along with a single &#8220;bootstrap.js&#8221; file that controls all the <a title="Server-side JavaScript on Wikipedia" href="http://en.wikipedia.org/wiki/Server-side_JavaScript" target="_blank">SSJS</a>, means that it ought to be fairly easy to port over single-page AppJet apps to Smart Platform.  Here&#8217;s some notes I&#8217;ve gathered whilst porting over an application that acts as a gateway between tarpipe&#8217;s REST connector and a Yahoo! Pipe, allowing you to send data to a Yahoo! Pipe for processing.</p></blockquote>
<h2>Request object</h2>
<p>In AppJet, you get the POSTed variables and the query-string parameters both in <code>request.params</code>. In Smart, the query-string parameters are in <code>request.query</code> with the raw string in <code>request.queryString</code>; POSTed variables are in <code>request.body</code> with the raw datastring in <code>request.content</code>.</p>
<h2>Dispatching</h2>
<p>In AppJet, you have the option to define different functions for handling different types of request e.g. GETs, POSTs and requests to different resources e.g. <code>/this</code>, <code>/that</code>. Smart uses <a title="Smart docs for use of Sammy" href="http://smart.joyent.com/docs/library/com/joyent/Sammy.html" target="_blank">Sammy</a>, which gives you a similar mechanism to choose which functions respond to different incoming requests, although you also have the option to use a single function <code>main(request) {...}</code> to handle all responses. A concrete example is:</p>
<p><pre class="brush: jscript;">AppJet:
    function get_resource() { ... }
Smart:
    GET(&quot;/resource&quot;, function() { });</pre></p>
<h2>Writing a response</h2>
<p>AppJet provides a default chrome that wraps an application, which you can remove by setting <code>page.setMode('plain')</code>; then you use functions like <code>print(response)</code> to send the respons. Smart does it slightly differently, where whatever you return from a function is sent as the response. It doesn&#8217;t seem possible to send HTTP header information.</p>
<h2>Making HTTP requests</h2>
<p>AppJet provides functions like <code>wpost</code> and <code>wget</code> to make HTTP calls. Smart provides the <code>system.http.request</code> function to do the same sort of thing. The difference in the returned response is that AppJet gave you a raw string of the response body, whereas Smart returns an object containing <code>headers</code> and <code>content</code> properties.</p>
<h2>Deployment</h2>
<p>The lack of an in-browser edit experience has been my complaint of late, but doing the Git bit to deploy my app to Smart was straightforward, and now it&#8217;s up at <a title="My Tarpipe 2 Yahoo! Pipes converter" href="http://f7e3dbf.smart.joyent.com" target="_blank">http://f7e3dbf.smart.joyent.com</a>.</p>
<p>Try it out with:</p>
<p><pre class="brush: jscript;">curl -d 'pipeId=lAUEoB1R3hGTqt6hggSecQ&amp;data={&quot;items&quot;:[{&quot;title&quot;:&quot;A title&quot;,&quot;description&quot;:&quot;Any description&quot;,&quot;link&quot;:&quot;http:\/\/example.com&quot;}]}' http://f7e3dbf.smart.joyent.com</pre></p>
<h2>Code</h2>
<p>For the sake of completion, here&#8217;s the source code. I&#8217;ve gone from this:</p>
<p><pre class="brush: jscript;">/* appjet:version 0.1 */
import(&quot;lib-json&quot;); 

var p = request.params;
var result = &quot;&quot;;
var output = &quot;&quot;; 

function serialize(obj) {
    var str = &quot;&quot;;
    for(var i in obj) {
        str += &quot;&amp;&quot;+encodeURIComponent(i)+&quot;=&quot;+encodeURIComponent(obj[i]);
    }
    return str.substring(1);
}
if(p &amp;&amp; p.data &amp;&amp; p.pipeId) {
    var data = JSON.parse(p.data);
    var pipeId = p.pipeId;
    var items = data.items;
    if(items) {
        var url = &quot;http://pipes.yahoo.com/pipes/pipe.run?_id=&quot;+pipeId+&quot;&amp;_render=json&quot;;
        // tarpipe only POSTs 1 item
        var result = wpost(url,{title:items[0].title,description:items[0].description});
        if(result) {
            result = JSON.parse(result);
            if(result) {
                output = result.value;
                if(!output.items[0].title) {
                    output.items[0].title = &quot;returned from Yahoo! Pipe at: &quot;+pipeId;
                }
                output = JSON.stringify(output);
            } else {
                result = &quot;bag result from Yahoo! Pipe at: &quot;+pipe;
            }
        } else {
            result = &quot;no result returned&quot;;
        }
    } else {
        result = &quot;no items in data input&quot;;
    }
} else {
    result = &quot;no data or no pipe input&quot;;
} 

page.setMode('plain');
output ? print(output) : print(result);</pre></p>
<p>To this:</p>
<p><pre class="brush: jscript;">system.use(&quot;com.joyent.Resource&quot;);
system.use(&quot;org.json.json2&quot;);

function serialize(obj) {
    var str = &quot;&quot;;
    for(var i in obj) {
        str += &quot;&amp;&quot;+encodeURIComponent(i)+&quot;=&quot;+encodeURIComponent(obj[i]);
    }
    return str.substring(1);
}

function main(request) {
	var p = request.content!=&quot;&quot; ? request.body : request.query;
	var result = &quot;&quot;;
	var output = &quot;&quot;;
	/* for debug input
	for (var i in p) {
		output += i+&quot;, &quot;+p[i]+&quot;\n&quot;;
	}
	return output;*/
	if(p &amp;&amp; p.data &amp;&amp; p.pipeId) {
	    var data = JSON.parse(p.data);
	    var pipeId = p.pipeId;
	    var items = data.items;
	    if(items) {
	        var url = &quot;http://pipes.yahoo.com/pipes/pipe.run?_id=&quot;+pipeId+&quot;&amp;_render=json&quot;;
	        // tarpipe only POSTs 1 item
	        var toPost = &quot;title=&quot;+items[0].title+&quot;&amp;description=&quot;+items[0].description;
	        var result = system.http.request(&quot;POST&quot;,url,null,toPost);
	        if(result &amp;&amp; result.content) {
	            result = JSON.parse(result.content);
	            if(result) {
	                output = result.value;
	                if(!output.items[0].title) {
	                    output.items[0].title = &quot;returned from Yahoo! Pipe at: &quot;+pipeId;
	                }
	                output = JSON.stringify(output);
	            } else {
	                result = &quot;bag result from Yahoo! Pipe at: &quot;+pipe;
	            }
	        } else {
	            result = &quot;no result returned&quot;;
	        }
	    } else {
	        result = &quot;no items in data input&quot;;
	    }
	} else {
	    result = &quot;no data or no pipe input&quot;;
	}
	return output || result;
}</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/691/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/691/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/691/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/691/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/691/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/691/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/691/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/691/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=691&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2009/07/16/notes-on-migrating-an-application-from-appjet-to-smart-platform/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ddf442971aebf6ce72763d02ead1c832?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
		<item>
		<title>Adapting WireIt to work with independent data stores</title>
		<link>http://jaybyjayfresh.com/2009/07/06/adapting-wireit-to-work-with-independent-data-stores/</link>
		<comments>http://jaybyjayfresh.com/2009/07/06/adapting-wireit-to-work-with-independent-data-stores/#comments</comments>
		<pubDate>Mon, 06 Jul 2009 23:45:37 +0000</pubDate>
		<dc:creator>Jonathan Lister</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[bbc]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[lshift]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[prototyping]]></category>
		<category><![CDATA[streams]]></category>
		<category><![CDATA[tarpipe]]></category>
		<category><![CDATA[wireit]]></category>
		<category><![CDATA[yahoo pipes]]></category>
		<category><![CDATA[yahoopipes]]></category>

		<guid isPermaLink="false">http://jaybyjayfresh.com/?p=669</guid>
		<description><![CDATA[I&#8217;ve been working during the last fortnight on the &#8220;Streams&#8221; project, which LShift, an IT consultancy in Shoreditch, are building in conjunction with the BBC. My part in this project has been to prototype the interface that a non-technical person would use to edit and create Streams, which are box-and-wire visual workflows similar to those [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=669&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working during the last fortnight on the &#8220;Streams&#8221; project, which <a title="LShift - technology from back to front" href="http://www.lshift.net/" target="_blank">LShift</a>, an IT consultancy in Shoreditch, are building in conjunction with the BBC. My part in this project has been to prototype the interface that a non-technical person would use to edit and create Streams, which are box-and-wire visual workflows similar to those found in Yahoo! Pipes or Tarpipe.</p>
<p>(The most interesting difference is that Streams combines Tarpipe&#8217;s event-driven model with Yahoo! Pipe&#8217;s modular data processing model. For more on this project and its ambition to open-sourcing, see <a title="Untangling the BBC's data feeds - LShift blog" href="http://www.lshift.net/blog/2009/05/08/untangling-the-bbcs-data-feeds" target="_blank">LShift&#8217;s</a> and the <a title="Introducing... BBC Feeds Hub on Radio Labs blog" href="http://www.bbc.co.uk/blogs/radiolabs/2009/04/introducing_bbc_feeds_hub.shtml" target="_blank">BBC&#8217;s</a> blog posts.)</p>
<p>I have been using <a title="WireIt - a JavaScript Wiring Library" href="http://javascript.neyric.com/wireit/" target="_blank">WireIt</a>, an open-source JavaScript library, to aid with the interface prototyping. Fortunately for me, WireIt&#8217;s latest version (v0.4), announced shortly before I started this project, includes a fully-featured &#8220;Wiring Editor&#8221;, which gets you up and running with the familiar Yahoo! Pipes-style editor.</p>
<p style="text-align:center;"><img class="aligncenter" title="WireIt Wiring Editor screenshot" src="http://img.skitch.com/20090706-bgrwghqusm9i4bjgak6wpt5un3.jpg" alt="" width="589" height="392" /></p>
<p>The brief for the prototype was to be able to complete a round-trip of loading up a Stream (stored as a document in <a title="The Apache CouchDB project" href="http://couchdb.apache.org/" target="_blank">CouchDB</a>), edit it, save it (back to CouchDB) and be able to load it up again.</p>
<p>I thought it would be helpful to bring to your attention the things you need to be aware of if you want to use WireIt&#8217;s Wiring Editor and adapt it to work with an independent source of module and workflow data.</p>
<h2>Stage 1 &#8211; different data formats</h2>
<p>It is hardly worth saying that there is no point trying to persuade your data store owners to change their data format so your job is made easier. Apart from this obvious need to convert from one data format to another, you also have to deal with the fact that WireIt only keeps hold of the data it needs to display and configure its modules.</p>
<p>The best place I could find to hook into the loading process was by overriding the function called after the load button is pressed:</p>
<p><pre class="brush: jscript;">WireIt.WiringEditor.prototype._onLoad = WireIt.WiringEditor.prototype.onLoad;
WireIt.WiringEditor.prototype.onLoad = function() {
    this.service.listWirings({group:true}, {
        success: function(result) {
            var responseText = result.responseText;
            if(responseText) {
	        this.pipes = convertFromStreams(responseText);
                this.pipesByName = {};
                this.renderLoadPanel();
                this.updateLoadPanelList();
                this.loadPanel.show();
            }
        },
        failure:function() {
            console.log('failure when loading, args:',arguments);
        },
        scope: this
    });
};</pre></p>
<p>The data format of a combination of blocks and wires in WireIt looks like this:</p>
<p><pre class="brush: jscript;">var modules = [
	{
		name: ,
		working: {}
	}
]
where &lt;em&gt;working&lt;/em&gt; is defined as:
working = {
	&quot;modules&quot;:[
		{
			&quot;name&quot;:&quot;FormContainer&quot;,
			&quot;config&quot;:{
				&quot;position&quot;:[115,58]
			},
			&quot;value&quot;:{
				&quot;email&quot;:&quot;&quot;,
				&quot;firstname&quot;:&quot;&quot;,
				&quot;happy&quot;:true,
				&quot;lastname&quot;:&quot;Dupont&quot;,
				&quot;title&quot;:&quot;Mr&quot;,
				&quot;website&quot;:&quot;&quot;
			}
		}],
	&quot;properties&quot;:{
		&quot;description&quot;:&quot;&quot;,
		&quot;name&quot;:&quot;teste&quot;
	},
	&quot;wires&quot;:[
		{
			&quot;src&quot;:{
				&quot;moduleId&quot;:0,
				&quot;terminal&quot;:&quot;br&quot;
			},
			&quot;tgt&quot;:{
				&quot;moduleId&quot;:1,
				&quot;terminal&quot;:&quot;tr&quot;
			}
		}
	]
}</pre></p>
<p>The <code>convertStreams</code> function changes each stream document available in CouchDB into the format above.</p>
<p>WireIt doesn&#8217;t keep hold of any properties you attach to blocks that aren&#8217;t used explicitly. This means you need to keep hold of any properties you need to save back to your data store. I did this by keeping a globally available variable, <code>WireIt.customFields</code>:</p>
<p><pre class="brush: jscript;">...
if(node.type) {
    WireIt.customFields.nodes[i].type = node.type;
} else {
    WireIt.customFields.nodes[i].terminal = node.terminal;
}
...</pre></p>
<h2>Stage 2 &#8211; loading the list of blocks from your data store</h2>
<p>As well as loading up descriptions of a full combination of blocks and wires, I wanted to load all the available blocks in CouchDB into WireIt so they&#8217;d be available for making workflows with.</p>
<p>The WireIt Wiring Editor doesn&#8217;t load its blocks from a remote system, you have to provide all the definitions in a JSON &#8220;language&#8221; file when you create the Wiring Editor. I hooked into the setup of the Wiring Editor after it had finished loading its backend-describing SMD file (see below for explanation of this SMD malarkey):</p>
<p><pre class="brush: jscript;">WireIt.WiringEditor.prototype.onSMDsuccess = function() {
	WireIt.customFields = {};
	this.populateModules();
};</pre></p>
<p>The <code>populateModules</code> function is responsible for turning the description of the block from CouchDB into the format WireIt uses for defining available blocks, which looks like this (<em>note it is different to the format used to describe a block that is part of a workflow, described above</em>):</p>
<p><pre class="brush: jscript;">var modules = [
	{
		&quot;name&quot;: &quot;detect_iplayer&quot;,
		container: {
			xtype: &quot;WireIt.FormContainer&quot;,
			type: &quot;regexp_replace&quot;,
			title: &quot;Detect iplayer and remove&quot;,
			icon: &quot;images/detect_iplayer.png&quot;,
			fields: [
				{&quot;inputParams&quot;: {&quot;name&quot;: &quot;caseinsensitive&quot;, &quot;label&quot;: &quot;case insensitive?&quot;, &quot;value&quot;:true}, &quot;type&quot;: &quot;boolean&quot;},
				{&quot;inputParams&quot;: {&quot;name&quot;: &quot;regexp&quot;, &quot;label&quot;: &quot;regular expression&quot;, &quot;value&quot;: &quot;(iplayer)&quot;}},
				{&quot;inputParams&quot;: {&quot;name&quot;: &quot;dotall&quot;, &quot;label&quot;: &quot;dot matches all?&quot;, &quot;value&quot;: false}, &quot;type&quot;: &quot;boolean&quot;},
				{&quot;inputParams&quot;: {&quot;name&quot;: &quot;multiline&quot;, &quot;label&quot;: &quot;multiline?&quot;, &quot;value&quot;: false}, &quot;type&quot;: &quot;boolean&quot;},
				{&quot;inputParams&quot;: {&quot;name&quot;: &quot;replacement&quot;, &quot;label&quot;: &quot;replacement&quot;, &quot;value&quot;: &quot;\\1&quot;}}
			],
			width:250,
			terminals: [
				{&quot;name&quot;: &quot;input&quot;, direction: [-1,0], offsetPosition: {left: 110, top: -15}},
				{&quot;name&quot;: &quot;positive&quot;, direction: [1,0], offsetPosition: {left: 60, bottom: -15}},
				{&quot;name&quot;: &quot;negative&quot;, direction: [1,0], offsetPosition: {right: 60, bottom: -15}}
			]
		}
	},
	...
]</pre></p>
<h2>Stage 3 &#8211; adding default layout</h2>
<p>The Streams data store doesn&#8217;t contain any information about how the blocks in a stream should be laid out, as this is not important to the execution of the streams. However, for loading a stream into WireIt, I wanted to give the blocks a default layout so they didn&#8217;t end up on top of each other.</p>
<p>I picked a layout that put the blocks equally spaced around a ring. This algorithm gives you the coordinates of a set of <code>count</code> blocks. It assumes the blocks are going to be square, and sets the radius of the ring so that the blocks would just touch if they were square.</p>
<p><pre class="brush: jscript;">function calculateLayout(count,width) {
	var coords = [];
	var n = count || 4;
	var h = width || 100;
	var radius = (n/Math.PI + 1.5)*h/Math.sqrt(2);
	var theta = 0;
	for (var i=0; i&lt;n; i++) {
		theta = 2*Math.PI*i/n;
		coords[i] = [];
		coords[i][0] = radius*(1+Math.cos(theta)); // x
		coords[i][1] = radius*(1-Math.sin(theta)); // y
	}
	return coords;
}</pre></p>
<h2>Stage 4 &#8211; different load/save API (and the limitation of yui-rpc)</h2>
<p>The Wiring Editor is hard-wired to use an implementation of <a title="Service Mapping Description Proposal - JSON Schema" href="http://groups.google.com/group/json-schema/web/service-mapping-description-proposal" target="_blank">JSON-Schema</a> called &#8220;YUI-RPC&#8221;, along with a defining Service Mapping Description (SMD &#8211; think WSDL for JavaScript). The down-side to this is that the implementation does not currently support HTTP verbs other than GET and POST, nor is it obvious how to extend the implementation in line with the spec. If your API requires the use of PUT (as CouchDB does to update or create named documents), then you will need to do something about this.</p>
<p>YUI-RPC supported what I needed for loading, so supporting CouchDB was only as hard as changing one of the method specifications:</p>
<p><pre class="brush: jscript;">&quot;listWirings&quot;: {
    &quot;transport&quot;: &quot;GET&quot;,
    &quot;envelope&quot;: &quot;URL&quot;,
    &quot;target&quot;: &quot;couchdb/_design/feeds/_view/join&quot;,
    &quot;parameters&quot;: [
        {&quot;name&quot;:&quot;group&quot;, &quot;type&quot;:&quot;boolean&quot;}
    ],
    &quot;description&quot;: &quot;Get a list of streams&quot;
}</pre></p>
<p>To support PUT for saving, I overrode <code>WireIt.WiringEditor.prototype.saveModule</code> and, deciding to go with what I know, stuck in a block of <a title="jQuery: The Write Less, Do More, JavaScript library" href="http://jquery.com/" target="_blank">jQuery</a> that I&#8217;d had hanging around from a test working with <a title="Documentation for CouchDB's HTTP API" href="http://wiki.apache.org/couchdb/HTTP_Document_API" target="_blank">CouchDB&#8217;s API</a>.</p>
<h2>General comments on prototyping with single-page applications</h2>
<p>I made the prototype as an application that could just be served as a single HTML page from a file: URI. I strongly support this over trying to make your prototype work with some web framework or other, as you will lose valuable time setting up the framework in the first place.</p>
<p>Working with HTML files loaded as files gives you a couple of special properties: you can read and write from the file system and make cross-domain XMLHttpRequests (on many browsers). I had to modify YUI&#8217;s Connect object a bit to support the cross-domain XHR requests. For more information on the special properties of HTML pages viewed over file: URI&#8217;s, see <a title="HTTP Requests section of a W3C paper submitted by Paul Downey of Osmosoft" href="http://www.w3.org/2008/security-ws/papers/osmosoft.html#HTTP%20Requests" target="_blank">these</a> <a title="File Saving section of a W3C position paper submitted by Paul Downey of Osmosoft" href="http://www.w3.org/2008/security-ws/papers/osmosoft.html#File%20Saving" target="_blank">sections</a> of a W3C position paper about <a title="A portable, non-linear, personal web notebook" href="http://www.tiddlywiki.com" target="_blank">TiddlyWiki</a> written by <a title="Osmosoft - open source from BT" href="http://osmosoft.com" target="_blank">Osmosoftonian</a> <a title="Paul Downey - sketching the web since 2008" href="http://blog.whatfettle.com" target="_blank">Paul Downey</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/669/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/669/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/669/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/669/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/669/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/669/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/669/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/669/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=669&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2009/07/06/adapting-wireit-to-work-with-independent-data-stores/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/ddf442971aebf6ce72763d02ead1c832?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>

		<media:content url="http://img.skitch.com/20090706-bgrwghqusm9i4bjgak6wpt5un3.jpg" medium="image">
			<media:title type="html">WireIt Wiring Editor screenshot</media:title>
		</media:content>
	</item>
		<item>
		<title>console.log in Safari doesn&#8217;t &#8220;apply&#8221;. Bad Safari.</title>
		<link>http://jaybyjayfresh.com/2008/11/10/consolelog-in-safari-doesnt-apply-bad-safari/</link>
		<comments>http://jaybyjayfresh.com/2008/11/10/consolelog-in-safari-doesnt-apply-bad-safari/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 16:08:59 +0000</pubDate>
		<dc:creator>jayfresh</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[cross browser]]></category>
		<category><![CDATA[cross-broswer]]></category>
		<category><![CDATA[crossbrowser]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[safari 3.1]]></category>
		<category><![CDATA[safari 3.1.2]]></category>

		<guid isPermaLink="false">http://jayfresh.wordpress.com/?p=335</guid>
		<description><![CDATA[It&#8217;s not unusual to want to write a cross-browser logging function akin to Firebug&#8217;s console.log(). The approach that you would expect to work could quite plausibly be this: We invoke the function with apply here so that implementations that can take multiple arguments receive them. However, this function breaks Safari (at least it does on [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=335&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://img.skitch.com/20081110-r1ek7cb6pecu9dfs9ewsby8b9n.jpg"><img class="alignright" title="Safari logo. Bad Safari" src="http://img.skitch.com/20081110-r1ek7cb6pecu9dfs9ewsby8b9n.jpg" alt="" height="75" /></a>It&#8217;s not unusual to want to write a cross-browser logging function akin to Firebug&#8217;s <code>console.log()</code>. The approach that you would expect to work could quite plausibly be this:<br />
<pre class="brush: jscript;">
function log() {
   if(console) {
      console.log.apply(this,arguments);
   }
}
</pre><br />
We invoke the function with <code>apply</code> here so that implementations that can take multiple arguments receive them.</p>
<p>However, this function breaks Safari (at least it does on version 3.1.2) &#8211; causing a helpful message <code>TypeError: type error</code>. At the moment, Safari&#8217;s <code>console.log</code> only takes one argument, so a way to fix the above function is as follows:<br />
<pre class="brush: jscript;">
function log(s) {
   if(console) {
      if(navigator.userAgent.toLowerCase().indexOf(&quot;applewebkit&quot;) != -1) {
         console.log(s);
      } else {
         console.log.apply(this,arguments);
      }
   }
}
</pre><br />
Quite why this is a problem is not clear to me. I did try to submit a <a title="Apple Bug Reporter" href="https://bugreport.apple.com/" target="_blank">bug report</a> to Apple, but arrived at this page instead:<br />
<img class="aligncenter" title="Apple's Bug Reporter has bugs" src="http://img.skitch.com/20081110-meaetg4wirnk62t6q8h6bbdf6f.jpg" height="212px" /><br />
I would appreciate it if someone would try and recreate the problem in Webkit &#8211; I&#8217;ve at least seen their bug tracker online.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/335/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/335/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/335/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=335&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2008/11/10/consolelog-in-safari-doesnt-apply-bad-safari/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7c29365aabf4babd23845685ab32058b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>

		<media:content url="http://img.skitch.com/20081110-r1ek7cb6pecu9dfs9ewsby8b9n.jpg" medium="image">
			<media:title type="html">Safari logo. Bad Safari</media:title>
		</media:content>

		<media:content url="http://img.skitch.com/20081110-meaetg4wirnk62t6q8h6bbdf6f.jpg" medium="image">
			<media:title type="html">Apple&#039;s Bug Reporter has bugs</media:title>
		</media:content>
	</item>
		<item>
		<title>SproutCore: smart clients, dumb servers</title>
		<link>http://jaybyjayfresh.com/2008/07/03/sproutcore-smart-clients-dumb-servers/</link>
		<comments>http://jaybyjayfresh.com/2008/07/03/sproutcore-smart-clients-dumb-servers/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 09:46:37 +0000</pubDate>
		<dc:creator>jayfresh</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[sproutcore]]></category>

		<guid isPermaLink="false">http://jayfresh.wordpress.com/?p=133</guid>
		<description><![CDATA[I heard about SproutCore recently, from an enthusiastic client-side web developer. I hadn&#8217;t heard about it, which is not entirely unsurprising as it turns out &#8211; SproutCore came out of hiding as something of a surprise at the recent Apple Worldwide Developers Conference, as the power behind the slick interfaces for Apple&#8217;s new suite of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=133&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I heard about <a href="http://www.sproutcore.com/">SproutCore</a> recently, from an enthusiastic client-side web developer. I hadn&#8217;t heard about it, which is not entirely unsurprising as it turns out &#8211; SproutCore came out of hiding as something of a surprise at the recent <a href="http://www.sproutcore.com/2008/05/20/sproutcore-session-time-is-set-for-wwdc/">Apple Worldwide Developers Conference</a>, as the power behind the slick interfaces for Apple&#8217;s new suite of <a href="http://www.apple.com/mobileme/">MobileMe</a> applications.</p>
<p>I&#8217;ve had a look. The clearly exciting thing, from my point of view, is that SproutCore produces static HTML, CSS and JavaScript. And it does this by asking you to write JavaScript. So, that&#8217;s a good thing. Static web applications are easy to scale and are looked on favourably by search engines. The interaction with any server-side (for data storage or web service access) is done using their simple REST API.</p>
<p>It almost looks like SproutCore has been designed as my web development framework of choice &#8211; the problem is that SproutCore uses a Ruby-based templating language called &#8220;<a href="http://rubyforge.org/projects/erubis/">Erubis</a>&#8221; to create what it terms &#8220;views&#8221; (in the <a href="http://en.wikipedia.org/wiki/Model-view-controller">Model-View-Controller tradition</a>); these are essentially the structure for the web pages. So the development behaviour becomes: do your coding in JavaScript and Ruby, compile the whole thing down to HTML, CSS and JavaScript and then upload to the server. I would have thought it would make more sense to write your templates in something that resembled HTML in the first place, and perhaps made use of JavaScript.</p>
<p>Notwithstanding the small deviation from the HTML, CSS, JavaScript toolset, SproutCore takes the idea of smart clients and dumb servers seriously, and does so more than any other web development framework out there.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/jayfresh.wordpress.com/133/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/jayfresh.wordpress.com/133/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/133/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/133/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/133/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=133&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2008/07/03/sproutcore-smart-clients-dumb-servers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7c29365aabf4babd23845685ab32058b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Script tags to do remote HTTP calls in Javascript</title>
		<link>http://jaybyjayfresh.com/2007/09/17/using-script-tags-to-do-remote-http-calls-in-javascript/</link>
		<comments>http://jaybyjayfresh.com/2007/09/17/using-script-tags-to-do-remote-http-calls-in-javascript/#comments</comments>
		<pubDate>Mon, 17 Sep 2007 17:24:22 +0000</pubDate>
		<dc:creator>jayfresh</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[cross domain scripting]]></category>
		<category><![CDATA[cross site scripting]]></category>
		<category><![CDATA[crossdomainscripting]]></category>
		<category><![CDATA[crosssitescripting]]></category>
		<category><![CDATA[jonathan lister]]></category>
		<category><![CDATA[jonathanlister]]></category>
		<category><![CDATA[tiddlywiki]]></category>
		<category><![CDATA[xmlhttprequest]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false">http://jayfresh.wordpress.com/2007/09/17/using-script-tags-to-do-remote-http-calls-in-javascript/</guid>
		<description><![CDATA[I&#8217;ve been racking my brains all afternoon trying to find a workable solution to the problem of not being able to make remote HTTP calls using javascript. This is an issue for me because so much of my work takes place inside a TiddlyWiki which, when viewed locally (from a file:// url) is a perfect [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=58&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been racking my brains all afternoon trying to find a workable solution to the problem of not being able to make remote HTTP calls using javascript. This is an issue for me because so much of my work takes place inside a <a href="http://www.tiddlywiki.com">TiddlyWiki</a> which, when viewed locally (from a file:// url) is a perfect environment for bypassing <a href="http://en.wikipedia.org/wiki/Same_origin_policy">standard AJAX security</a> and creating mashups. The problem comes when I want to put a TiddlyWiki online to show off what I&#8217;ve done or to let other people use it &#8211; the local behaviour is not replicated and my mashups go <a href="http://ninjawords.com/kaput">kaput</a>.</p>
<p>There are <a href="http://ajaxpatterns.org/On-Demand_Javascript">several</a> <a href="http://ajaxpatterns.org/IFrame_Call">ways</a> of getting around this security restriction, known as Javascript&#8217;s same-origin policy, but they generally involve using iframes and other files on your own server. I wanted to keep everything in one self-contained file, so I pretty much ruled these out. The idea of using a local proxy was thrown out for the same reasons.</p>
<p>A found a <a href="http://rockstargirl.org/sandbox/bidynodes/">some info</a> that covered &#8220;dynamic <code>Script</code> tags&#8221;, which requires the remote server to serve you a tailored javascript file that called a function you supplied the name of, with the data you wanted returned as a parameter to that function, but that was really just a facade on top of another proxy story.</p>
<p>Then I hit upon <a href="http://www.hunlock.com/blogs/Howto_Dynamically_Insert_Javascript_And_CSS">this wonderful website</a>, which gave an insight into an API architecture being adapted by, amongst others, Yahoo!. The idea revolves around the API itself returning JSON encapsulated in a function call, so the body of the response is essentially the parameter to the function. You add a <code>Script</code> tag to your page with the API call as the <code>src</code> attribute and when the browser loads the script, it ends up calling the function, which you write support for in your code.</p>
<p><pre class="brush: jscript;">
// adapted from http://www.hunlock.com/blogs/Howto_Dynamically_Insert_Javascript_And_CSS
var headID = document.getElementsByTagName(&quot;head&quot;)[0];         
var newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.onload=scriptLoaded;
newScript.src = 'http://api.flickr.com/services/feeds/photos_public.gne?tags=sunset&amp;amp;amp;format=json';
headID.appendChild(newScript);

jsonFlickrFeed = function(feed) {
   // deal with the feed!
};

// when the script is finished, remove the script node we added
// removeNode is a custom function defined in the TiddlyWiki source code: http://svn.tiddlywiki.org/Trunk/core/js/Dom.js
// It ensures that the eventhandler is removed before deletion
scriptLoaded = function() {
	removeNode(newScript);
};
</pre></p>
<p>It&#8217;s simple, elegant and easy to work with. There are two alternative implementations that I&#8217;ve seen today: the first and simplest for the server to support, is <a href="http://www.flickr.com/services/api/response.json.html">exemplified</a> by <a href="http://www.flickr.com">Flickr</a> &#8211; the function call wrapped around the response data is fixed and you have to know what it is to write support for it <em>[edit - they do support the next method too]</em>; <a href="http://pipes.yahoo.com">Yahoo! Pipes</a> (and more generally, Yahoo!&#8217;s other <a href="http://developer.yahoo.com/common/json.html">developer API&#8217;s</a>) <a href="http://discuss.pipes.yahoo.com/Message_Boards_for_Pipes/threadview?m=tm&amp;bn=pip-DeveloperHelp&amp;tid=264&amp;mid=283&amp;tof=-1&amp;rt=2&amp;frt=2&amp;off=1">supports</a> the second method &#8211; the API takes the name of a callback function as a parameter and then wraps the data in a call to this function, which takes away the dependency on knowing the specific function to write support for.</p>
<p>This isn&#8217;t the perfect solution, as it leaves you wide open to exploitation from <a href="http://en.wikipedia.org/wiki/Cross_site_scripting">cross-site scripting</a>, so I don&#8217;t recommend using this with API&#8217;s that you don&#8217;t trust. I feel pretty safe using Yahoo!&#8217;s API&#8217;s, but someone less salubrious could inject whatever they wanted in there. You don&#8217;t really want that when the script has access to the global object and, therefore, everything on your page.</p>
<p>This takes me one step closer to making it easier to replicate your offline TiddlyWiki environment online&#8230; Hurrah&#8230;</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/jayfresh.wordpress.com/58/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/jayfresh.wordpress.com/58/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/58/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/58/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/58/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=58&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2007/09/17/using-script-tags-to-do-remote-http-calls-in-javascript/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7c29365aabf4babd23845685ab32058b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
		<item>
		<title>Too many cooks spoil the DOM (getting content out of page elements)</title>
		<link>http://jaybyjayfresh.com/2007/09/05/too-many-cooks-spoil-the-dom-getting-content-out-of-page-elements/</link>
		<comments>http://jaybyjayfresh.com/2007/09/05/too-many-cooks-spoil-the-dom-getting-content-out-of-page-elements/#comments</comments>
		<pubDate>Wed, 05 Sep 2007 15:56:42 +0000</pubDate>
		<dc:creator>jayfresh</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[btosmosoft]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[innerHTML]]></category>
		<category><![CDATA[innerText]]></category>
		<category><![CDATA[jonathan lister]]></category>
		<category><![CDATA[jonathanlister]]></category>
		<category><![CDATA[nodevalue]]></category>
		<category><![CDATA[quirksmode]]></category>
		<category><![CDATA[textcontent]]></category>
		<category><![CDATA[value]]></category>
		<category><![CDATA[W3C]]></category>

		<guid isPermaLink="false">http://jayfresh.wordpress.com/2007/09/05/too-many-cooks-spoil-the-dom-getting-content-out-of-page-elements/</guid>
		<description><![CDATA[I frequently find myself wanting to refer to the contents of an element on a web page, having got hold of that element in the DOM. However, I equally frequently forget how to access this content. The confusion arises because there are various ways to get hold of the content of an element: nodeValue, value, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=52&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I frequently find myself wanting to refer to the contents of an element on a web page, having got hold of that element in the DOM. However, I equally frequently forget how to access this content.</p>
<p>The confusion arises because there are various ways to get hold of the content of an element: <code>nodeValue</code>, <code>value</code>, <code>data</code>, <code>textContent</code>, <code>innerText</code> and <code>innerHTML</code> all seem to do the job in different circumstances. In the hope that I&#8217;m not the only one with this problem, I looked into the matter&#8230;</p>
<p>In a nutshell:</p>
<ul>
<li><code>nodeValue</code> returns attributes or text (read/write)</li>
<li><code>value</code> returns the text content of an attribute (read)</li>
<li><code>data</code> is used to access text content of a node (read/write)</li>
<li><code>textContent</code> returns the text content of a node and its descendents (read/write)</li>
<li><code>innerText</code> returns the text content of a node and its descendents (read/write)</li>
<li><code>innerHTML</code> returns the HTML contained by an element (read/write)</li>
</ul>
<p><strong><code>nodeValue</code></strong>, counter-intuitively, does not return the text content of a node such as a paragraph i.e. it is not a W3C analogue of <code>innerHTML</code>. <code>nodeValue</code> is in the <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-F68D080" title="nodeValue in the DOM Core specification" target="_blank">DOM Core specification</a> and is <a href="http://www.quirksmode.org/dom/w3c_core.html#nodeinformation" title="nodeValue on quirksmode.org">well supported</a> by browers. It is a read/write attribute.</p>
<p>This table from <a href="http://developer.mozilla.org/en/docs/DOM:element.nodeValue" title="Mozilla developer pages" target="_blank">developer.mozilla.org</a> shows the return value of accessing nodeValue on various nodes:</p>
<table cellpadding="1" cellspacing="1">
<tr style="background-color:#55bbff;">
<td>Attr</td>
<td>value of attribute</td>
</tr>
<tr style="background-color:#55bbff;">
<td>CDATASection</td>
<td>content of the CDATA Section</td>
</tr>
<tr style="background-color:#55bbff;">
<td>Comment</td>
<td>content of the comment</td>
</tr>
<tr style="background-color:#55bbff;">
<td>Document</td>
<td>null</td>
</tr>
<tr style="background-color:#55bbff;">
<td>DocumentFragment</td>
<td>null</td>
</tr>
<tr style="background-color:#55bbff;">
<td>DocumentType</td>
<td>null</td>
</tr>
<tr style="background-color:#55bbff;">
<td>Element</td>
<td>null </td>
</tr>
<tr style="background-color:#55bbff;">
<td>NamedNodeMap</td>
<td>null</td>
</tr>
<tr style="background-color:#55bbff;">
<td>EntityReference</td>
<td>null </td>
</tr>
<tr style="background-color:#55bbff;">
<td>Notation</td>
<td>null </td>
</tr>
<tr style="background-color:#55bbff;">
<td>ProcessingInstruction</td>
<td>entire content excluding the target</td>
</tr>
<tr style="background-color:#55bbff;">
<td>Text</td>
<td>content of the text node</td>
</tr>
</table>
<p><strong><code>value</code></strong> returns the text value of a node&#8217;s attribute. This does not work with text nodes. <code>value</code> is in the <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-221662474" title="value in the DOM Core Specification" target="_blank">DOM Core Specification</a> and it is <a href="http://www.quirksmode.org/dom/w3c_core.html#attributes" title="value on quirksmode.org" target="_blank">very poorly supported</a> in Windows IE, although Firefox does support it. It is a read-only attribute.</p>
<p><strong><code>data</code></strong> is used to address the content of a text node. It is the same as nodeValue for that node. <code>data</code> is in the <a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-72AB8359" title="data in the DOM Core Specification" target="_blank">DOM Core Specification</a> and it is <a href="http://www.quirksmode.org/dom/w3c_core.html#data" title="data on quirksmode.org">well supported</a> by browsers. It is a read/write attribute.</p>
<p><strong><code>textContent</code></strong>/<strong><code>innerText</code></strong> returns the text contained in a node and its descendants, ignoring any contained tags. Whilst <code>textContent</code> is in the <a href="http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#Node3-textContent" title="textContent in the DOM Level 3 Core Specification" target="_blank">DOM Level 3 Core Specification</a> and it is not really supported at all except in Firefox, <code>innerText</code> is <a href="http://www.quirksmode.org/dom/w3c_html.html#all" title="innerText on quirksmode.org" target="_blank">well supported</a> by browsers, the exception being buggy support in Mozilla 1.75. Both are read/write attributes.</p>
<p><strong><code>innerHTML</code></strong> returns the markup contained in a node and its descendants. Whilst <code>innerHTML</code> is not in a W3C specification, most browsers <a href="http://www.quirksmode.org/dom/w3c_html.html#all" title="innerHTML on quirksmode.org" target="_blank">support it</a> and it is often <a href="http://www.quirksmode.org/dom/innerhtml.html" title="DOM vs. innerHTML on quirksmode.org" target="_blank">faster</a> than W3C DOM methods. It is a read/write attribute.</p>
<p>I&#8217;m heavily indebted to <a href="http://www.quirksmode.org" title="quirksmode.org" target="_blank">quirksmode.org</a> and the <a href="http://www.w3.org" title="W3C website" target="_blank">W3C</a> DOM specifications for this information.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/jayfresh.wordpress.com/52/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/jayfresh.wordpress.com/52/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jayfresh.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jayfresh.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jayfresh.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jayfresh.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jayfresh.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jayfresh.wordpress.com/52/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jayfresh.wordpress.com/52/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jayfresh.wordpress.com/52/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jaybyjayfresh.com&amp;blog=786754&amp;post=52&amp;subd=jayfresh&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jaybyjayfresh.com/2007/09/05/too-many-cooks-spoil-the-dom-getting-content-out-of-page-elements/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/7c29365aabf4babd23845685ab32058b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">jayfresh</media:title>
		</media:content>
	</item>
	</channel>
</rss>
