<?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:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Software As She's Developed &#187; Javascript</title>
	<atom:link href="http://softwareas.com/tag/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://softwareas.com</link>
	<description>Mahemoff's Podcast/Blog - Web, Programming, Usability from the Author of 'Ajax Design Patterns' (AjaxPatterns.org)</description>
	<lastBuildDate>Mon, 26 Jul 2010 16:52:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- podcast_generator="podPress/8.8" - maintenance_release="8.8.4" -->
		<copyright>Copyright &amp;#xA9; Software As She's Developed 2010 </copyright>
		<managingEditor>michael@mahemoff.com (Software As She's Developed)</managingEditor>
		<webMaster>michael@mahemoff.com (Software As She's Developed)</webMaster>
		<category>posts</category>
		<ttl>1440</ttl>
		<itunes:keywords></itunes:keywords>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary>Mahemoff's Podcast/Blog - Web, Programming, Usability from the Author of 'Ajax Design Patterns' (AjaxPatterns.org)</itunes:summary>
		<itunes:author>Software As She's Developed</itunes:author>
		<itunes:category text="Society &amp; Culture"/>
		<itunes:owner>
			<itunes:name>Software As She's Developed</itunes:name>
			<itunes:email>michael@mahemoff.com</itunes:email>
		</itunes:owner>
		<itunes:block>No</itunes:block>
		<itunes:explicit>no</itunes:explicit>
		<itunes:image href="http://softwareas.com/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<image>
			<url>http://softwareas.com/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
			<title>Software As She's Developed</title>
			<link>http://softwareas.com</link>
			<width>144</width>
			<height>144</height>
		</image>
		<item>
		<title>Video Sync with WebSocket and Node</title>
		<link>http://softwareas.com/video-sync-with-websocket-and-node</link>
		<comments>http://softwareas.com/video-sync-with-websocket-and-node#comments</comments>
		<pubDate>Fri, 18 Jun 2010 17:45:13 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[WebSocket]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=918</guid>
		<description><![CDATA[

Wanting to explore WebSocket, I made a demo that syncs videos for all users looking at the page (See the Code). Any user can "take control", so that the other videos will follow the controller's video. Writing it was a cinch with the Javascript WebSocket API in the client, and the very straightforward Node WebSocket [...]]]></description>
			<content:encoded><![CDATA[<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/r90ti4MbecM&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/r90ti4MbecM&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>

<p>Wanting to explore WebSocket, I made a demo that syncs videos for all users looking at the page (<a href="http://gist.github.com/443933">See the Code</a>). Any user can "take control", so that the other videos will follow the controller's video. Writing it was a cinch with the Javascript WebSocket API in the client, and the very straightforward <a href="http://github.com/miksago/node-websocket-server">Node WebSocket Server</a> powering the server.</p>

<p>Note it's just a simple demo - there's no security model here and there's a very simple sync mechanism: When a "slave" client receives the latest duration, it adds a second to account for lag, and moves the video iff there's a 5-second discrepancy.</p>

<p>How does a WebSocket client look? Well, it looks a lot simpler than a traditional Comet client. Initiate the connection with "new WebSocket":</p>

<div class="igBar"><span id="ljavascript-5"><a href="#" onclick="javascript:showPlainTxt('javascript-5'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-5">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> conn;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; $_<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"#join"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">onclick</span> = <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; conn = <span style="color: #003366; font-weight: bold;">new</span> WebSocket<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"ws://localhost:8000/test"</span><span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>Upload a message to the server with send():</p>

<div class="igBar"><span id="ljavascript-6"><a href="#" onclick="javascript:showPlainTxt('javascript-6'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-6">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">video.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"timeupdate"</span>, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>iAmControlling<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> conn.<span style="color: #006600;">send</span><span style="color: #66cc66;">&#40;</span>video.<span style="color: #006600;">currentTime</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span>, <span style="color: #003366; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>Receive a message from the server with conn.onmessage():</p>

<div class="igBar"><span id="ljavascript-7"><a href="#" onclick="javascript:showPlainTxt('javascript-7'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-7">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">conn.<span style="color: #006600;">onmessage</span> = <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #66cc66;">&#40;</span>ev<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>matches = ev.<span style="color: #006600;">data</span>.<span style="color: #006600;">match</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066FF;">/^pause <span style="color: #66cc66;">&#40;</span>.+<span style="color: #66cc66;">&#41;</span>$/</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; video.<span style="color: #006600;">pause</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; video.<span style="color: #006600;">currentTime</span> = matches<span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;color:#800000;">1</span><span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; ...</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>And when it's time to draw the curtains, close the connection with another one-liner:</p>

<div class="igBar"><span id="ljavascript-8"><a href="#" onclick="javascript:showPlainTxt('javascript-8'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-8">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">$_<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"#leave"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">onclick</span> = <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; conn.<span style="color: #000066;">close</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; ...</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>The server is also rather tiny. It mostly just broadcasts (sends to all clients) any incoming message and it's up to the clients to deal with it. Which is why I say there's no real security model here.</p>

<p>As you can see in the above snippets, "video" plays an excellent cameo role here, with its <a href="http://diveintohtml5.org/video.html">equally simple API</a>. One downside, which others <a href="http://www.systemerror.co.uk/2010/05/06/html5-video-real-world/">have mentioned too</a>, is the lack of styling in the default video controls. It's great the API supports automatic controls, but it's unfortunate there's no CSS manipulation. In this case, the "slave" browsers should be able to see the time, but not have the ability to change the progress. I hope this changes in the future, because the API is otherwise very powerful without compromising simplicity. Until then, <a href="http://www.longtailvideo.com/support/forums/jw-player/feature-suggestions/10383/html5-version-of-jw-player">libraries</a> will arise to fill the gap.</p>

<p>The demo works in both Chrome and Safari (and they play nice simultaneously).</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/video-sync-with-websocket-and-node/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Using BrowserScope to Detect Geolocation Support</title>
		<link>http://softwareas.com/using-browserscope-to-detect-geolocation-support</link>
		<comments>http://softwareas.com/using-browserscope-to-detect-geolocation-support#comments</comments>
		<pubDate>Thu, 27 May 2010 22:32:28 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Browserscope]]></category>
		<category><![CDATA[Geolocation]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=911</guid>
		<description><![CDATA[About Browserscope

Browserscope is a very cool tool coming out of Steve Souders' performance efforts and being developed by Steve along with Lindsey Simon. It's part of a trend towards crowdsourcing browser info, in similar vein to TestSwarm, for testing specific code, and along the lines of what I did with WebWait, which is to support [...]]]></description>
			<content:encoded><![CDATA[<h4>About Browserscope</h4>

<p><a href="http://browserscope.org">Browserscope</a> is a very cool tool coming out of Steve Souders' performance efforts and being developed by Steve along with Lindsey Simon. It's part of a trend towards crowdsourcing browser info, in similar vein to <a href="http://testswarm.com">TestSwarm</a>, for testing specific code, and along the lines of what I did with <a href="http://webwait.com">WebWait</a>, which is to support multiple people benchmarking a website at once. (Though I've not set up reporting on it - one day...)</p>

<p>So anyway, Browserscope began life as a way to benchmark just performance, but is now a general-purpose tool for crowdsourcing tests about anything browsers do, e.g. checking for security vulnerabilities is one vital application. HTML5 does not miss out - <a href="http://html5test.com">HTML5Test.com</a> has been ported over too - see <a href="http://beta.html5test.com">beta.html5test.com</a>.</p>

<h4>Geolocation Test</h4>

<p>I decided to make my own test recently, to see what extent Geolocation is being supported by the browsers. Run the test against your browser here (it will upload only information about whether geo is supported, not your actual geolocation data):</p>

<p><a href="http://test.mahemoff.com/geo.html">http://test.mahemoff.com/geo.html</a></p>

<p>The results so far indicate browsers either don't support it, or support accuracy+lat+lon. I was hoping to see at least direction, and would &lt;3 to see altitude! But it will have to wait.</p>

<h4>How to Make your Own Browserscope Test</h4>

<p>If you ever wanted to know how every browser under the sun handles a particular something, Browserscope is your new hotness. It makes it trivial. Register with Browserscope to get the boilerplate code. Then you just write an app that does the exercises and builds up a hashmap of the info you want to collect, and BAM, submit it. The hashmap should have values between 1 and 1000. Do that, and you'll end up with a nice summary page showing your test results aggregated across all browsers that ran them.</p>

<p>The submission is taken care of by some boilerplate code - it uses on-demand Javascript to pass the data back to the third-party BrowserScope domain (you host the test yourself). Aside from writing the actual test and promoting its location, the only thing you have to do is make a nice UI to show the users what you just did, and perhaps get their consent before uploading. I think those are actually two things Browserscope could automate too, at least providing a nice default UI which test creators can customise.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/using-browserscope-to-detect-geolocation-support/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Another HTML5 Tidbit: Web SQL Database</title>
		<link>http://softwareas.com/another-html5-tidbit-web-sql-database</link>
		<comments>http://softwareas.com/another-html5-tidbit-web-sql-database#comments</comments>
		<pubDate>Thu, 27 May 2010 22:10:04 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[offline storage]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Web SQL Database]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=908</guid>
		<description><![CDATA[I coded up a small demo of Web SQL Database. As the demo points out, notice you can hit reload and the data remains, being that it's one of the several techniques for offline storage.

There's not much to say about Web SQL - you either know SQL already, in which case it's fairly straightforward and [...]]]></description>
			<content:encoded><![CDATA[<p>I coded up a <a href="http://project.mahemoff.com/sql.html">small demo of Web SQL Database</a>. As the demo points out, notice you can hit reload and the data remains, being that it's one of the several techniques for offline storage.</p>

<p>There's not much to say about Web SQL - you either know SQL already, in which case it's fairly straightforward and just a matter of squeezing your SQL calls into the conventions of the API, like any other SQL framework as, lamentably, there's never been any kind of standardisation on the wrappers that go around SQL - or you don't know SQL, in which case there's your bottleneck child if you intend to use Web SQL Database for offline storage.</p>

<p><a href="http://dev.w3.org/html5/webdatabase/">Web SQL Database</a> lies at the other end of the complexity spectrum from <a href="http://dev.w3.org/html5/webstorage/">Web Storage</a> (aka localStorage and sessionStorage), which is simply a big ol' hashmap for your domain. The complexity is fairly manageable, though, as there's literally a generation of SQL know-how out there, and hopefully ActiveRecord-like libraries on their way.</p>

<p><a href="http://www.w3.org/TR/IndexedDB/">IndexedDB</a> promises to offer a third way - more like the hashmap approach, but with some of the indexing-based performance gains SQL has to offer. No browsers have implemented it yet, though you can build an experimental windows version using a third-party <a href="http://code.google.com/p/indexeddb/wiki/build">Firebreath implementation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/another-html5-tidbit-web-sql-database/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upcoming: UXCampEurope and SWDC</title>
		<link>http://softwareas.com/upcoming-uxcampeurope-and-swdc</link>
		<comments>http://softwareas.com/upcoming-uxcampeurope-and-swdc#comments</comments>
		<pubDate>Sat, 22 May 2010 21:07:49 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[HCI UXCamp UX]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[SWDC]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[UXCamp]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=900</guid>
		<description><![CDATA[



Google I/O is over and I'll post a bit about the HTML5 hack session I ran later, but here I want to highlight a couple of upcoming sessions in Europe:

UXCampEurope. If this is anything like the Bay Area and London UX camps I've been fortunate to attend, it will be huge, and being Europe-wide and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://uxcampeurope.com"><img src="http://picupper.com/2010/05/22/1d796f3fd74641c3ae7177c4b090d.gif"/></a></p>

<p><a href="http://swdc-central.com/"><img src="http://picupper.com/2010/05/22/4630263600_125e317727_o.jpg" /></a></p>

<p>Google I/O is over and I'll post a bit about the HTML5 hack session I ran later, but here I want to highlight a couple of upcoming sessions in Europe:</p>

<p><strong>UXCampEurope.</strong> If this is anything like the Bay Area and London UX camps I've been fortunate to attend, it will be huge, and being Europe-wide and in Berlin, this expectation might just be met. I was sitting on the browser along with @mattlucht hitting refresh 10 times a second when the tickets were released at the start of the year! I'll set up a slot called "What did HTML5 ever do for users, anyway?". I'm planning to overview some of the features of HTML5 and its evolution from Ajax, and ask how it might be used to improve UX. It's a camp, so I'll also be hoping to collect contributions and writing them up somewhere.</p>

<p><strong>SWDC.</strong> The first Scandinavian Web Developer Conference and Peter Svensson is organising, so I know it will be an awesome event, and the <a href="http://swdc-central.com/">sessions</a> speak for themselves. I've bumped into the guy twice in the past month - he travelled from Stockholm to DC for JSConf, and again to SF for I/O. My session is on the mobile day, called "HTML5 Gives You Wings", focusing on HTML5 techniques for performance and app-like behaviour. Here's the summary:</p>

<blockquote>
Welcome to the dynamic world of mobile development, where new browsers stay close to the edge and HTML5 is already a reality. Despite the impressive advances, many mobile apps are still bottlenecked by the network and compact processors continue to lag behind their desktop counterparts. So how can HTML5 help? This talk will focus on those features of HTML5 that are interesting for performance optimisation and the techniques for emulating native apps, such as offline data storage.
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/upcoming-uxcampeurope-and-swdc/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Offline Apps with Application Cache: Quickstart, Tips, and Deep Dive</title>
		<link>http://softwareas.com/offline-apps-with-application-cache-quickstart-tips-and-deep-dive</link>
		<comments>http://softwareas.com/offline-apps-with-application-cache-quickstart-tips-and-deep-dive#comments</comments>
		<pubDate>Wed, 19 May 2010 07:58:59 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=886</guid>
		<description><![CDATA[I've been mucking with AppCache, aka ApplicationCache. It's the secret sauce that lets you build offline apps, which is great for performance and fabulous for pretending to be an iPhone app when you're not.

Quickstart an Offline App

As with most HTML5 technologies, the basic usage is quite simple:


Create a trivial trio of HTML, CSS, and JS [...]]]></description>
			<content:encoded><![CDATA[<p>I've been mucking with AppCache, aka ApplicationCache. It's the secret sauce that lets you build offline apps, which is great for performance and fabulous for pretending to be an iPhone app when you're not.</p>

<h3>Quickstart an Offline App</h3>

<p>As with most HTML5 technologies, the basic usage is quite simple:</p>

<ol>
<li><strong>Create a trivial trio of HTML, CSS, and JS files, maybe with an image or two.</strong> (Or reuse an existing toy app.)</li>
<li><strong>Link to a "cache manifest" file from your HTML file's <tt>html</tt> tag</strong> like so:
<div class="igBar"><span id="lhtml-10"><a href="#" onclick="javascript:showPlainTxt('html-10'); return false;">PLAIN TEXT</a></span></div><div class="syntax_hilite"><span class="langName">HTML:</span><br /><div id="html-10">
<div class="html"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">&lt;html</span></a> manifest=<span style="color: #ff0000;">"clock.manifest"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span> </div></li></ol></div>
</div></div><br />
</li>
<li><strong>Make the manifest file.</strong> It's just the literal phrase "CACHE MANIFEST" on the top line (I know, bit random), followed by the list of files in your app:
<pre>
CACHE MANIFEST
clock.html
clock.css
clock.js
clock.png
</pre>
</li>
<li><strong>Mark it as MIME type text/cache-manifest.</strong> If you're SSHing to a virtual host (like I did with Dreamhost), all you need here is a one-line .htaccess file:
<pre>
AddType text/cache-manifest manifest
</pre>
</li>
</ol>

<p>That's it. Now those files above will be cached locally and won't need to be downloaded again next time. To test it, load the site, shut down your net connection, and reload. It's still there innit.</p>

<p>It works the same on your app-phone - on iPhone or Android (or others maybe), load the site, switch to airport mode, go back to the browser and reload ... the site's still there. Where it gets really fun is making it into a regular app:</p>

<ul>
<li>On iPhone, bookmark the site with the Safari "+" button, choose "Add to Home Screen", and the app will be sitting alongside all your other apps on the home screen.</li>
<li>On Android, bookmark the app in the browser. Hold your finger down somewhere empty on the home screen, choose add "Shortcuts" | "Bookmark", and choose the bookmark you've made.</li>
</ul>

<p>You could do the same with any website of course, but it's particularly cool when the website is an offline one...it works just like a regular app!</p>

<h3>Practical Tips and Troubleshooting</h3>

<h4>Purging the Cache</h4>

<p>In practical terms, you are quickly going to come up the no. 1 problem of developing against a cache. How do you purge it whenever you update your code?</p>

<p><a href="http://mdn.beonex.com/en/Offline_resources_in_Firefox">Simple.</a> You only need to make an arbitrary change to the cache manifest file, so just include a version number in the comment:</p>

<p><pre>
CACHE MANIFEST
&#35; v1
clock.html
clock.css
clock.js
clock.png
</pre></p>

<p>Keep revving it up every time you change <em>any</em> file, because changing those files alone won't have any effect. And if it's getting serious, you'll want to practice the principles of DRY and continuous integration by automating this process.</p>

<h4>Ridding yourself of Errors</h4>

<p>An unfortunate thing happens when there's a downloading error: The whole thing silently fails. Until debugging tools get better, if you find your app's not updating, you ought to check each of the resources specified in the manifest really, really, carefully.</p>

<h4>Cached Resources</h4>

<p>Cache manifests are not exempt from standard caching rules, so the manifest itself, as well as other files might be cached. Pain. <a href="http://diveintohtml5.org/offline.html">A good solution</a> is to use the following Apache directives to .htaccess:
<pre>
ExpiresActive On
ExpiresDefault
</pre></p>

<h4>That MIME Type</h4>

<p>Things might fail if the Cache Manifest MIME type is wrong, so use your browser's debugging tools or a service like <a href="http://web-sniffer.net/">Web Sniffer</a> to check it (thanks <a href="http://www.thecssninja.com/javascript/how-to-create-offline-webapps-on-the-iphone">CSS Ninja</a>).</p>

<h4>The Wording</h4>

<p>The wording can also trip you up. Be really sure it's exactly "CACHE MANIFEST" at the start of the file. Again, better debugging tools in the future will help here.</p>

<h3>The Fancy Stuff</h3>

<p>All of the above is enough to get up and running with an offline app, and maintaining it too. But wait, there's complexity too!</p>

<h4>Fine Control Over What Gets Cached</h4>

<p>The cache manifest file actually allows three kinds of resources:</p>

<ul>
  <li><strong>Online resources that can be cached (CACHED).</strong> As shown in the example above, it's the stuff that's available for caching.</li>
  <li><strong>"Fallback" resources in case a file isn't cached (FALLBACK). </strong>These are like catch-all email addresses; any resource that's not cached, is a candidate for a fallback. There's a pattern-matching algorithm to map resources (which mightn't have been cached) to other resources (which hopefully have been cached). For <a href="http://diveintohtml5.org/offline.html">example</a>, you probably wouldn't cache every wikipedia article, so the fallback section would ensure a special "offline.html" page is shown for those missing articles. </li>
  <li><strong>Online-only resources (NETWORK)</strong> Resources which should never be cached, e.g. it would be a good idea not to cache stock prices if people were making million-dollar decisions on the back of what they see on your possibly-cached web application.</li>
</ul>

<p>The syntax (adapted from the WHATWG example):</p>

<p><pre>
CACHE MANIFEST
&#35; a comment
&#35; v37
&#35; (version number unnecessary
&#35; but recommended for cache purposes)</pre></p>

<p>&#35; the following "CACHE:" is optional;
&#35; a special case because top of file
&#35; is cache by default
&#35; CACHE:
images/sound-icon.png
images/background.png
&#35; note that each file has to be put on its own line</p>

<p>FALLBACK:
/ /sorry-i-am-offline.html</p>

<p>NETWORK:
/stocks/*
</p>

<h4>Checking if We're Online</h4>

<p>window.navigator.onLine ... try it now in your console (and try it again with your connection off).</p>

<h4>Monitoring State and State Changes</h4>

<p>What do you notice about all the app cache stuff above? It's all declarative, no Javascript. But you can go on to do extra stuff with Javascript too, via the <a href="application-cache-api">Application Cache API</a>. (I am somewhat skeptical about the applications for this API, since simple and declarative is the way to go for something as potentially hairy as offline...but that's for another rant.)</p>

<p>The window is effective tied one-to-one to the cache object, so you can just access the cache with window.applicationCache. For example, you can get cache state with window.applicationCache.status, try it now in your console. It will probably be zero...the possible values range from 0 to 5, representing:
UNCACHED, IDLE CHECKING, DOWNLOADING, UPDATEREADY, OBSOLETE. (These constants are also available on the cache object, i.e. window.applicationCache.UNCACHED is 0.)</p>

<p>There are also event handlers to monitor event state: onchecking, onerror, onnoupdate, ondownloading, onprogress, onupdateready, oncached, onobsolete.</p>

<h4>Forcing Updates</h4>

<p>applicationCache.update() will force an update, i.e. start downloading the application again if the manifest has changed. However, it won't suddenly  switch over after downloading. To do so would be to pull the rug from under your live, running, application. It will be there next time. But if you do want it right away, use applicationCache.swapCache().</p>

<h4>Offline Mobile Apps: It's More than Application Cache</h4>

<p>Application cache certainly is a critical feature of mobile apps; it's a basic user expectation that a mobile app starts right away, unlike a complex web app which must be downloaded. However, there are other things too. For example, offline storage. That's another feature of HTML5, comes in many incaranations, and something for another day. The other really big deal is the UI. Of course, you need to simulate certain UI features of the native apps if you want your web app to go native. Hence, libraries like IUI, jQTouch, and Apple's secret PastryKit. On the input side, your UI must also <a href="ajaxian.com/archives/mouseovers-on-touch-devices">handle touch events</a>, something some of the aformentioned brand of libraries will support. Finally, there will be specific features of the platform that can help; <a href="http://ajaxian.com/archives/iphone-full-screen-webapps">for example</a>, setting the home screen icon and going full-screen so the browser chrome doesn't show up.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/offline-apps-with-application-cache-quickstart-tips-and-deep-dive/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Audio/Video Tag: Don&#8217;t Forget to load() before you play()</title>
		<link>http://softwareas.com/audiovideo-tag-dont-forget-to-load-before-you-play</link>
		<comments>http://softwareas.com/audiovideo-tag-dont-forget-to-load-before-you-play#comments</comments>
		<pubDate>Fri, 30 Apr 2010 03:33:29 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Video]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=870</guid>
		<description><![CDATA[

This is a gotcha that will catch a lot of people out because it goes against the expectation that you just change an image's appearance by setting its "src", done. And also, it's a deviation from the more general convention that you change DOM properties declaratively to make stuff happen. Probably for good reason, given [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://picupper.com/2010/04/29/music.jpg" /></p>

<p>This is a gotcha that will catch a lot of people out because it goes against the expectation that you just change an image's appearance by setting its "src", done. And also, it's a deviation from the more general convention that you change DOM properties declaratively to make stuff happen. Probably for good reason, given the temporal nature of audio and video playback, but just beware it's a different model.</p>

<p><strong>Bottom line is - load() between changing src and play()ing</strong>:</p>

<div class="igBar"><span id="ljavascript-12"><a href="#" onclick="javascript:showPlainTxt('javascript-12'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-12">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> play<span style="color: #66cc66;">&#40;</span>url<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> audio = document.<span style="color: #006600;">querySelector</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"audio"</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; audio.<span style="color: #006600;">src</span> = url;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; audio.<span style="color: #006600;">load</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// !HUL|_O! PAY ATTENTI0N!</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; audio.<span style="color: #006600;">play</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>A lot of online sources talk about play() and omit to mention this vital fact, because they're only play()ing a single track...and the first track works fine. This is an oddity - you can just call play() the first time and it will automatically load. This happens whether you set "src" in the initial HTML's "audio" tag or whether you set it programatically. I did some <a href="http://jsfiddle.net/QkGEr/3/">fiddling</a> and it looks like the behaviour is the same in Chrome and Firefox. It's like the track is auto-load()ed the first time you set its source. (And note that <a href="http://hacks.mozilla.org/2009/12/autobuffering-video-in-firefox/">Firefox doesn't auto-buffer</a> so that's nothing to do with it.)</p>

<p><a href="http://www.devx.com/webdev/Article/43324/1954">devx</a> has you covered on this topic, and points out the subtle issues which you would need to look at for a quality production:</p>

<blockquote>
However, media by its very nature is a time-spanning process. You're working with both the need to load and cache audio and video files and the network connection, which itself can prove to be a challenge that's usually not a factor for most non-temporal resources. For these reasons, when dealing with video and audio on the web, if you want to take control of the process in any way, you have to work asynchronously, tying into the various events that are passed back to the client from the media-serving website. Table 4 (taken directly from the HTML 5 documentation) provides a full listing of the various events and when they are dispatched.
...
Of all the events in Table 4, perhaps the most useful are the canplay and canplaythrough events. The first, canplay, will fire when enough data has been loaded for the video player to start actually rendering content constructively, even if not all of the data has been loaded. The canplaythrough event, on the other hand, will fire when the data has essentially completely loaded into the browser's buffer, making it possible to play the video all the way through without the need to pause and retrieve more content.
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/audiovideo-tag-dont-forget-to-load-before-you-play/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Yoink: Extracting All Scripts and Stylesheets on the Page</title>
		<link>http://softwareas.com/yoink-extracting-all-scripts-and-stylesheets-on-the-page</link>
		<comments>http://softwareas.com/yoink-extracting-all-scripts-and-stylesheets-on-the-page#comments</comments>
		<pubDate>Mon, 26 Apr 2010 00:14:43 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[yoink]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=860</guid>
		<description><![CDATA[

This here is a script that will put the code of all scripts and stylesheets into a single variable. Usage:

PLAIN TEXT

JAVASCRIPT:
yoink&#40;function&#40;all&#41; &#123;
&#160; console.log&#40;"scripts", all.scripts&#41;; // string array
&#160; console.log&#40;"stylesheets", all.stylesheets&#41;; // string array
&#125;&#41;; 




As you can see, you have to provide a callback because this stuff is asynchronous. It downloads the files one at a time [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://pic4.picturetrail.com/VOL715/2562261/21942942/362689087.jpg" /></p>

<p>This here is a script that will put the code of all scripts and stylesheets into a single variable. Usage:</p>

<div class="igBar"><span id="ljavascript-15"><a href="#" onclick="javascript:showPlainTxt('javascript-15'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-15">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">yoink<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>all<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; console.<span style="color: #006600;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"scripts"</span>, all.<span style="color: #006600;">scripts</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// string array</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; console.<span style="color: #006600;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"stylesheets"</span>, all.<span style="color: #006600;">stylesheets</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// string array</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>As you can see, you have to provide a callback because this stuff is asynchronous. It downloads the files one at a time to keep things simple and without using any fancy-pants Ajax queueing library. And right now, timeouts won't be too graceful. Also, browsers will typically allow scripts and stylesheets to work cross-domain, but of course XHR won't. So any external scripts and stylesheets are unfortunately out of reach and will not be captured. This is an especially tragic circumstance in the case where they are hosted on a different subdomain. But, as they say, "hey". I don't know what that means, but, as they say, "hey".</p>

<p>Yoink will download inline scripts (script tags with bodies), remote scripts (script tags having a "src" attribute), inline style attributes (elements having a "style" attribute), inline style tags (style tags with bodies), and remote stylesheets (links of type "text/css").</p>

<p>There are several purposes. I did a quick hack version of this a while back to improve logging info; in principle, a logging method could introspect on the source tree to show extra context info (locate the log message I'm currently outputting, and then say which line it's coming from, for example).</p>

<p>In the case of <a href="softwareas.com/spa-hacks">Single Page Applications</a> a la TiddlyWiki, a plugin might use Yoink to inline all the remote content.</p>

<p>Right now, I'm more interested in using it for browser extensions, such as the Feature Creep extension <a href="http://mini.softwareas.com/a-few-browser-extensions-id-like-to-see-or-ma">I suggested</a>, to show what's happening on the page. Some of that stuff you can work out by inspecting the DOM, but other stuff ... show me the code!</p>

<p>Get it here - http://gist.github.com/378850. Shown below for convenience:</p>

<div class="igBar"><span id="ljavascript-16"><a href="#" onclick="javascript:showPlainTxt('javascript-16'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-16">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">function</span> yoink<span style="color: #66cc66;">&#40;</span>complete<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> all=<span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; scripts: <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>,</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; stylesheets: <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">function</span> downloadResources<span style="color: #66cc66;">&#40;</span>urls, onComplete<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> resources = <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> inlineResource<span style="color: #66cc66;">&#40;</span>index<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>index==urls.<span style="color: #006600;">length</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; onComplete<span style="color: #66cc66;">&#40;</span>resources<span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> xhr = <span style="color: #003366; font-weight: bold;">new</span> XMLHttpRequest<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; xhr.<span style="color: #000066;">open</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"GET"</span>, urls<span style="color: #66cc66;">&#91;</span>index<span style="color: #66cc66;">&#93;</span>, <span style="color: #003366; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; xhr.<span style="color: #006600;">onreadystatechange</span> = <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>xhr.<span style="color: #006600;">readyState</span>!=<span style="color: #CC0000;color:#800000;">4</span><span style="color: #66cc66;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>xhr.<span style="color: #000066;">status</span>==<span style="color: #CC0000;color:#800000;">200</span><span style="color: #66cc66;">&#41;</span> resources.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span>xhr.<span style="color: #006600;">responseText</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; &nbsp; inlineResource<span style="color: #66cc66;">&#40;</span>index+<span style="color: #CC0000;color:#800000;">1</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; xhr.<span style="color: #006600;">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;color:#800000;">0</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> scripts = document.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"script"</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> scriptSources = <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i=<span style="color: #CC0000;color:#800000;">0</span>; i&lt;scripts.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> </div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>scripts<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">src</span><span style="color: #66cc66;">&#41;</span> scriptSources.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span>scripts<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">src</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// remote</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">else</span> all.<span style="color: #006600;">scripts</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span>scripts<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">innerHTML</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #009900; font-style: italic;">// inline</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; downloadResources<span style="color: #66cc66;">&#40;</span>scriptSources, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>resources<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; all.<span style="color: #006600;">scripts</span> = all.<span style="color: #006600;">scripts</span>.<span style="color: #006600;">concat</span><span style="color: #66cc66;">&#40;</span>resources<span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> styles = document.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"styles"</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i=<span style="color: #CC0000;color:#800000;">0</span>; i&lt;styles.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span> all.<span style="color: #006600;">stylesheets</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span>styles<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>; <span style="color: #66cc66;">&#125;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> allElements = document.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"*"</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i=<span style="color: #CC0000;color:#800000;">0</span>; i&lt;allElements.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> inlineStyle = allElements<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">getAttribute</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"style"</span><span style="color: #66cc66;">&#41;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>inlineStyle<span style="color: #66cc66;">&#41;</span> all.<span style="color: #006600;">stylesheets</span>.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span>inlineStyle<span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> links = document.<span style="color: #006600;">getElementsByTagName</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"link"</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> cssHrefs = <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i=<span style="color: #CC0000;color:#800000;">0</span>; i&lt;links.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>links<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">type</span>==<span style="color: #3366CC;">"text/css"</span><span style="color: #66cc66;">&#41;</span> cssHrefs.<span style="color: #006600;">push</span><span style="color: #66cc66;">&#40;</span>links<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">href</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; downloadResources<span style="color: #66cc66;">&#40;</span>cssHrefs, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>resources<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; all.<span style="color: #006600;">stylesheets</span> = all.<span style="color: #006600;">stylesheets</span>.<span style="color: #006600;">concat</span><span style="color: #66cc66;">&#40;</span>resources<span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; complete<span style="color: #66cc66;">&#40;</span>all<span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div></li></ol></div>
</div></div>

<p><br /></p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/yoink-extracting-all-scripts-and-stylesheets-on-the-page/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SPA Hacks: Hacks Emerging From the World of Single-Page Web Apps</title>
		<link>http://softwareas.com/spa-hacks</link>
		<comments>http://softwareas.com/spa-hacks#comments</comments>
		<pubDate>Wed, 14 Apr 2010 13:46:58 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JSConf]]></category>
		<category><![CDATA[Presentation]]></category>
		<category><![CDATA[SPA]]></category>
		<category><![CDATA[TiddlyWiki]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=853</guid>
		<description><![CDATA[This is a permalink for my JSConf.US talk. Full slides are online here:

THE LOST HACKS:
Ridiculous browser tricks from the world of single-page Applications


The talk will overview TiddlyWiki and Single-Page Apps, and then cover eight specific hacks:


File access without browser extensions
Javascript-HTML chameleon files
SVG-VML chameleon files
Inline SVG
iFrame squriting
Script islands
Embedded images
Fragment IDs


I'll be posting a link to the [...]]]></description>
			<content:encoded><![CDATA[<p>This is a permalink for my <a href="http://jsconf.us/2010/schedule.html#saturday">JSConf.US talk</a>. Full slides are online here:</p>

<p><a href="http://prez.mahemoff.com/jsconf2010-spahacks.html">THE LOST HACKS:
Ridiculous browser tricks from the world of single-page Applications
</a></p>

<p>The talk will overview TiddlyWiki and Single-Page Apps, and then cover eight specific hacks:</p>

<ul>
<li>File access without browser extensions</li>
<li>Javascript-HTML chameleon files</li>
<li>SVG-VML chameleon files</li>
<li>Inline SVG</li>
<li>iFrame squriting</li>
<li>Script islands</li>
<li>Embedded images</li>
<li>Fragment IDs</li>
</ul>

<p>I'll be posting a link to the slideshow notes from here. I'm pleased to say the nascent <a href="http://tiddlyslidy.com/#TiddlySlidy">TiddlySlidy app</a> has been a pleasure to dogfood it in.</p>

<p>[<a href="http://delicious.com/search?p=jsconfcred&#038;chk=&#038;context=main|&#038;fr=del_icio_us&#038;lc=">Image credits</a>]</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/spa-hacks/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automagic Event Registration</title>
		<link>http://softwareas.com/automagic-event-registration</link>
		<comments>http://softwareas.com/automagic-event-registration#comments</comments>
		<pubDate>Mon, 22 Mar 2010 10:43:33 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax Patterns]]></category>
		<category><![CDATA[Dependency Injection]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JQuery]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=829</guid>
		<description><![CDATA[Further to last night's post on custom events, I've set things up now to use "magic event registration". It's a little like the auto-wiring facility of a dependency injection container. It's quite simple really - the app's initialisation sequence does this:


Register all components that might listen to something.
Register all events they might listen to.
For each [...]]]></description>
			<content:encoded><![CDATA[<p>Further to <a href="http://mini.softwareas.com/playing-with-jquery-custom-events-good-tip-fr">last night's post on custom events</a>, I've set things up now to use "magic event registration". It's a little like the <a href="http://static.springsource.org/spring/docs/2.5.6/reference/beans.html#beans-factory-autowire">auto-wiring facility of a dependency injection container</a>. It's quite simple really - the app's initialisation sequence does this:</p>

<ul>
<li>Register all components that might listen to something.</li>
<li>Register all events they might listen to.</li>
<li>For each listener method among the components, automatically bind the event to it.</li>
</ul>

<p>In code:</p>

<div class="igBar"><span id="ljavascript-21"><a href="#" onclick="javascript:showPlainTxt('javascript-21'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-21">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> components = <span style="color: #66cc66;">&#91;</span>siteFrame, singleTrial, trialController, statsZone, tableView, analysis, rawView, graphView<span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #003366; font-weight: bold;">var</span> eventTypes = <span style="color: #66cc66;">&#91;</span><span style="color: #3366CC;">"trialCreate"</span>, <span style="color: #3366CC;">"trialUpdate"</span>, <span style="color: #3366CC;">"trialSuspend"</span>, <span style="color: #3366CC;">"trialRun"</span>, <span style="color: #3366CC;">"trialComplete"</span><span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; $.<span style="color: #006600;">each</span><span style="color: #66cc66;">&#40;</span>components, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>i,component<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; $.<span style="color: #006600;">each</span><span style="color: #66cc66;">&#40;</span>eventTypes, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>i,eventType<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> handler = component<span style="color: #66cc66;">&#91;</span>eventType<span style="color: #66cc66;">&#93;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>handler<span style="color: #66cc66;">&#41;</span> $<span style="color: #66cc66;">&#40;</span>document<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">bind</span><span style="color: #66cc66;">&#40;</span>eventType, handler<span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>A component looks like:</p>

<div class="igBar"><span id="ljavascript-22"><a href="#" onclick="javascript:showPlainTxt('javascript-22'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-22">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">statsZone = <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; trialCreate: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e, trial<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; ...</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span>,</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; trialUpdate: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>e, trial<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; ...</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>And elsewhere in the code, the events it listens to get triggered through the normal jQuery custom events mechanism:</p>

<div class="igBar"><span id="ljavascript-23"><a href="#" onclick="javascript:showPlainTxt('javascript-23'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-23">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">$<span style="color: #66cc66;">&#40;</span>document<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">trigger</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"trialUpdate"</span>, trial<span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>Part of this is based on what I said last night, which is (a) I'm keeping things simple - hence everything happens at startup and all the instances are singleton classes; (b) consequently, events are global, rather than being attached to any particular component.</p>

<p>Stepping back, what were the alternatives to this design:</p>

<ul>
<li><p>Components register themselves as listeners - this would be the purist OO answer, i.e. keeping objects autonomous. A perfectly cromulent solution, but a little more redundancy than it needs to be. If objects really do have consistently named listener methods, it's just as easy to handle registration automagically.</p></li>
<li><p>The initialisation routine manually wires up components to events. It has a certain Python-like "explicit" feel to it, but again is quite pointless if we can instead do it automagically.</p></li>
</ul>

<p>So where does the automagic model fall down? If we are doing things dynamically, it would get more complicated and would, for example, require objects to register upon their creation. So I think that's still okay. Another problem could be if a single method was listening to more than one event type, since this technique assumes it's one-to-one from event type to methods. But that's okay too - I actually had this problem and it was simply solved by getting both handlers to delegate to a third, common, handler:</p>

<div class="igBar"><span id="ljavascript-24"><a href="#" onclick="javascript:showPlainTxt('javascript-24'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-24">
<div class="javascript"><ol><li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #003366; font-weight: bold;">var</span> trialController = <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; trialCompleteOrCreate: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; ...</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #66cc66;">&#125;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">trialController.<span style="color: #006600;">trialCreate</span> = trialController.<span style="color: #006600;">trialComplete</span> = trialController.<span style="color: #006600;">trialCompleteOrCreate</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>I realised while working on TiddlySpace there's a lot to be said for dependency injection style patterns in Javascript, and it's not happening yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/automagic-event-registration/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Joining Google</title>
		<link>http://softwareas.com/joining-google</link>
		<comments>http://softwareas.com/joining-google#comments</comments>
		<pubDate>Tue, 16 Mar 2010 11:48:21 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Navel-Gazing]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=801</guid>
		<description><![CDATA[I mentioned I'm moving on from Osmosoft a few weeks ago and after 12days and a week of doing much less than one could ever have imagined, it's time to announce where I'm going: Google. I'll be joining Google as a Chrome developer advocate, which means focusing on HTML5, Javascript, the Chrome browser, ChromeOS, and [...]]]></description>
			<content:encoded><![CDATA[<p>I mentioned I'm moving on from Osmosoft <a href="http://softwareas.com/twelve-days-of-tiddlywiki-twelve-days-of-osmosoft">a few weeks ago</a> and after <a href="http://12days.osmosoft.com">12days</a> and a week of doing much less than one could ever have imagined, it's time to announce where I'm going: Google. I'll be joining Google as a Chrome developer advocate, which means focusing on HTML5, Javascript, the Chrome browser, ChromeOS, and related technologies.</p>

<p>I'm very excited about the role, for reasons best explained in terms of a timeline for the web. I see the history of web technologies divided into three phases and I believe we're currently in the transition from the second to the third phase. Which is the starting context for this role.</p>

<h3>Dark Ages (Web as a Black Art)</h3>

<p><img src="http://upload.wikimedia.org/wikipedia/commons/b/b6/French-gendarme.jpg" width="200" /></p>

<p>Rich web apps were hard work. Black art even. During this phase, I spent most of my time on server-side languages - Perl, PHP, Java/J2EE - and Javascript was a weird sideline. Taking an interest in the user experience, I always wanted to know more about this black art, since it's the web technologies that touch the user and have the most direct influence over their experience with any application. But what paid the bills in the late '90s and early noughties was form submissions and page refreshes. And most Javascript content was odd little ticker tape scripts you could download, not too much to learn from, and always difficult to achieve in one's spare time. I think this was the frustrating experience for many web developers: not enough time and hard work. I did get by and pick up a few tricks here and there, but things only took off when the A-word was unleashed ...</p>

<h3>Ajax Era (Web as an Established Practice)</h3>

<p><img src="http://farm3.static.flickr.com/2112/2368225695_7f87aaedba.jpg" width="200" /></p>

<p>Everything changed five years ago, on February 18, 2005. Jesse James Garrett hopped in the shower, came up with the term "Ajax", and published his thoughts on this rising architectural pattern. Many people bristle at the notion that a simple term, for something people were already doing, can make such an impact. "BUT I already knew how to do that!" they cry. Good for them. But the fact is, Ajax allowed the whole developer community to rally around this style of application. Events, blogs, books, libraries, tools, the whole thing flourished. I got seriously interested, <a href="http://softwareas.com/ajax-podcast">recorded a podcast explaining the topic</a>,  and started diving into all the existing applications, which ultimately led to <a href="http://ajaxpatterns.org">the Ajax Patterns wiki</a>. All those applications, and many featured in the book, were created in the Dark Ages by brilliant pioneers who had scant resources to learn from. Today, such applications can be created at exponentially faster rates. This is thanks to improved knowledge, improved libraries, and improved tools.</p>

<p>There are historical analogies to this era, e.g. the rapid rise of the automobile industry once all parts were in place. In that case, it was more a matter of discovering new physical and engineering principles, whereas with Ajax, it was a superficial act. The browsers were already there, with a killer feature like IE's XMLHttpRequest sitting largely unnoticed for five years. Few people had taken the time to really understand how they worked. It was the Ajax term to trigger the boom.</p>

<h3>HTML5 Era (Web on an Improved Platform)</h3>

<p><a href="http://www.flickr.com/photos/neatocoolville/140303972/"><img width="200" src="http://farm1.static.flickr.com/54/140303972_dc5fa8a7bd.jpg" /></a></p>

<p> (I hesitate to call this the era of HTML5, as many things happening are outside HTML5, notably improvements to CSS and the core Javascript/ECMAscript language. But HTML5 is increasingly becoming <a href="http://www.quirksmode.org/blog/archives/2010/03/html5_apps.html">a brand</a>, much like Ajax in its heyday, a term that's familiar to anyone with a passing interest in technology.)</p>

<p>The starting point for this era is the success of open web technologies. While we continue to learn more each day, we have the basics in place today. We know how to harness HTML, CSS, Javascript to make powerful libraries and  applications on the existing browsers. This is where the Ajax Era landed us. We have seen some genius hacks. In fact, we have seen MANY ingenius hacks. <a href="http://ajaxpatterns.org/On-Demand_Javascript">On-Demand Javascript and JSONP</a>, for example, are completely fundamental to the way business is done on the web these days, and is utterly a hack. Full credit to those who came up with them, but these hacks can only go so far. They can increase programming complexity, impact on performance, and cause security threats for those not fully-versed in their capabilities. And that's just for the things we <em>can</em> do. The bigger problem is that we are heavily limited in our functionality on Ajax-Era technologies. We can't do rich graphics or video, for example. So the next stage is all about improving the underlying platform. It's not something an application programmer,  however heroic, can do on their own. It's something that has to involve improvements from the platform providers, i.e. the browser manufacturers and others.</p>

<p>To draw a line in the sand, take IE6. Although <a href="http://ie6isolderthanyourgrandpa.com">it was created back in 2001</a>, we could do far more with it in 2004 (e.g. Google Maps) than we could in 2001, and we can do far more with it in 2010 than we could in 2004. This is because of all the knowledge, libraries, and tools the Ajax Era has provided. <strong>However, we're in serious plateau mode now. We can continue to squeeze out 1-percenters, but the low-hanging fruit was plucked and digested a long time ago. The next stage has to be an improvement to the underlying platform, and that's what's going on today with modern web browsers.</strong></p>

<p>Once you say "okay we're now going to build the next-gen web platform", you're not just going to add support for round corners. So there's been a truckload of effort going on, in HTML5 and beyond. Graphics in the form of canvas and SVG and WebGL and CSS3, media in the form of audio and video tags, semantic markup improvements, new form controls, offline storage, support for location-awareness. And much more.</p>

<p>We have the new platform and alongside it, we have the activity of understanding how to use the new platform. Not just understanding the parts, but the whole. How do you put all these things together in meaningful ways. Can we show custom-font text on a canvas? If so, how? And when does it make sense?  And how to avoid performance problems? Or, to take another example, what kind of CSS transforms can we use to render videos? And since we can grab image data from the videos, what are some cool things we can do with that data? And all the while, where's the graceful degradation story here? How do these apps look in older browsers? Most of the talk so far has been on the capabilities of the platform, not patterns of usage.</p>

<p>All these new capabilities take us to the place we've been aiming for all along: <a href="http://softwareas.com/ajax-lite-versus-ajax-deluxe">true applications deluxe</a>, not just "html++". Of course, there's plenty of room for both of these, but we're now in a place where we can really build true applications with all the capabilities of a traditional native experience. We're seeing it in a big way in mobile space. The new model is all about sandboxing, doing away with the filesystem, and explicit permissions. Exactly what the web's good for. They're not only a good fit technically, but they've become the ubiquitous lingua franca among the programming community. The technologies are familiar, as are the patterns of UI design and code composition. Those patterns will continue to evolve with HTML5 and associated technologies.</p>

<p>We're just scratching the surface here; there are exciting times ahead!</p>

<hr />

<p>I'm not an official Googler yet, nor even a Noogler, as I've taken time off to chill, smell the roses, and pursue a few projects (like <a href="http://twitter.com/mahemoff/status/10534324953">dusting off</a> the <a href="http://mahemoff.com">homepage</a> and ... watch this space. Actually, watch <a href="http://twitter.com/mahemoff">that</a> space). I'm starting in about a month. And of course, even when I am official, this blog continues to be my own opinions, caveat emptor yadda.</p>

<p>The role covers EMEA and I'm still based in London. Despite not starting just yet, I'm looking forward to participating in <a href="http://www.london-gtug.org/Venue">tonight's Chrome/Chromium OS and HTML5 London event</a>. See you there!</p>

<p>(<a href="http://www.techmeme.com/100315/p10">I'm not the only one to announce a move to Google at this time.</a> I'm looking forward to meeting and working with many of my talented future colleagues.)</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/joining-google/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
