<?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</title>
	<atom:link href="http://softwareas.com/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>Wed, 25 Aug 2010 11:40:31 +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>Ten Reasons Why IE6 Development is Significantly Better in 2010 than 2001 (But Still Painful)</title>
		<link>http://softwareas.com/ten-reasons-why-ie6-development-is-significantly-better-in-2010-than-2001-but-still-painful</link>
		<comments>http://softwareas.com/ten-reasons-why-ie6-development-is-significantly-better-in-2010-than-2001-but-still-painful#comments</comments>
		<pubDate>Wed, 25 Aug 2010 11:40:31 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[IE6]]></category>
		<category><![CDATA[Javascript]]></category>

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

This post mentions IE6 everywhere, but it&#8217;s not about IE6 at all. In my standard rant on the three ages of web development, a standard sub-rant is our improved ability to develop on IE6:


Although it was created back in 2001, we could do far more with it in 2004 (e.g. Google Maps) than we could [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://ie6isolderthanyourgrandpa.com"><img src="http://farm5.static.flickr.com/4115/4926371730_a47d5e97c6.jpg" width="250" /></a></p>

<p>This post mentions IE6 everywhere, but it&#8217;s not about IE6 at all. In my standard rant on <a href="http://softwareas.com/joining-google">the three ages of web development</a>, a standard sub-rant is our improved ability to develop on IE6:</p>

<blockquote>
Although it was created back in 2001, 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.
</blockquote>

<p>I cite the <a href="http://ie6isolderthanyourgrandpa.com/">3,286 day old</a> application as an example because it&#8217;s the one browser that&#8217;s still around and still must be targeted by a significant number of developers (despite the best intentions of even MS employees to <a href="http://twitter.com/reybango/status/20401971054">&#8220;drive a stake into IE6s heart&#8221;</a>, and thankfully, the number is starting to dwindle). It&#8217;s the 120-year old who&#8217;s witnessed the transition from horse-and-cart transportation, to men on the moon, and is still here today to speculate on the eagerly awaited ChatRoulette relaunch. We could ask how effective Netscape Navigator development is in 2010, but since no-one actually does that, any answers would be hypothetical. IE6 is something many people worked with pre Ajax era and something some people still work with post Ajax, so it&#8217;s a specimen that can be used to show how Ajax changed the world.</p>

<p>(You could do this kind of analysis for any platform, e.g. the design pattern phenomenon means that you would approach a C++ app very differently today than you would have in 1987, even with the same language and compiler.)</p>

<p>In the Ajax era, we made like engineers and got smart about how to do the best we could with the laws of physics our universe imposed on us.  (Versus the new HTML5 era, where we build a better universe.) I decided to make this post to be a bit more explicit about why IE6 development is significantly better today than when IE6 came out. And by &#8220;better&#8221;, I mean faster and more powerful, if still a slow, frustrating, and not-very-powerful development cycle compared to the modern browsers.</p>

<p>With no further adieu, IE6 development is better today than in 2001 because &#8230;</p>

<p><strong>10. Libraries</strong> If only we had jQuery in 2001. If only &#8230;</p>

<p><strong>9. Knowledge</strong> JavaScript was allegedly <a href="http://www.crockford.com/javascript/javascript.html">the world&#8217;s most misunderstood language</a> in 2001. Now it&#8217;s well-understood, good parts and bad. And so is the DOM. An abundance of blogs, forums, books, and conferences.</p>

<p><strong>8. Patterns</strong> We not only know how Javascript and the DOM work, we have idioms, patterns, and best practices for putting it into action.</p>

<p><strong>7. Performance</strong> IE6 is orders of magnitudes slower than today&#8217;s browsers, so managing performance is certainly important, and these days, we know much more about how to make web apps run faster, thanks to the efforts of Steve Souders et al.</p>

<p><strong>6. Tools</strong> Tools from MS and others have come along over the years to improve the development experience. Firebug or Webkit Devtools they are not, but at least IE6 debugging is more than just alert boxes these days.</p>

<p><strong>5. Developers, Developers, Developers</strong> Finding savvy web developers these days is vastly easier than it was pre-Ajax, when front-end development was a black art.</p>

<p><strong>4. Show Me the Source</strong> We now have plenty of examples to learn from, both online, where View Source is your friend, and in the open source code repositories of the world.</p>

<p><strong>3. Browser Mechanics</strong> We understand the quirks of each browser much better now, and that certainly includes the many well-documented quirks of IE6 and how to deal with them.</p>

<p><strong>2. Attitude</strong> Those examples also overcome the psychological barrier, a key impediment to IE6 development. In the absence of any decent examples, it was easier for developers to shrug their shoulders and say it&#8217;s all too hard. If that sounds too mystical, see <a href="http://www.sptimes.com/News/121799/Sports/Bannister_stuns_world.shtml">4 minute mile</a>. &#8220;Ajax&#8221; is more than a set of technologies, it&#8217;s also the recognition that these kinds of apps are possible.</p>

<p><strong>1. Development is Just Easier These Days.</strong> No matter what kind of development you&#8217;re doing, development is just easier in 2010. Blogs, Forums, Twitter, Code Repositories, etc are improved, so this will impact on IE6 development or any other form of development, though there&#8217;s a law of diminishing returns here.</p>

<p>IE6 development is still a tough effort and thankfully becoming less of a requirement as people shift to modern browsers, or at least IE8. You know a browser is on its way out when &#8220;because employees are less likely to use Facebook&#8221; is one of its most compelling advantages. The Ajax era had a profound effect on the way we develop and what we know to be possible, but that era is mostly over, and that law of diminishing returns is kicking in hard. Hence, we make a new, better, platform to keep progressing what&#8217;s possible.</p>

<p>Will the rush of HTML5 work make IE6 development in 2020 even more doubleplusgood than in 2010? Not really. There will be a few odd improvements, but overall, HTML5 is about improving the platform, which means developers will increasingly be focused on doing things IE6 will thankfully never even try to do. The HTML5 world subsumes the Ajax world, so you get the double benefit &#8211; all of these ten Ajax benefits multiplied by all of the new features of the platform.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/ten-reasons-why-ie6-development-is-significantly-better-in-2010-than-2001-but-still-painful/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ruby Script to Localise Images for Offline HTML</title>
		<link>http://softwareas.com/ruby-script-to-localise-images-for-offline-html</link>
		<comments>http://softwareas.com/ruby-script-to-localise-images-for-offline-html#comments</comments>
		<pubDate>Mon, 16 Aug 2010 00:18:36 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[offline]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=953</guid>
		<description><![CDATA[I'm maintaining a custom HTML5 slide framework. A little similar to the canonical slides.html5rocks.com insofar as, well, it's HTML5 and slides horizontally! But the key difference is that it's very markup-based - What You See Is What You Need (WYSIWYN) - so creating new slides is easy.

Anyway, I did something similar with TiddlySlides a little [...]]]></description>
			<content:encoded><![CDATA[<p>I'm maintaining a custom HTML5 slide framework. A little similar to the canonical <a href="http://slides.html5rocks.com/">slides.html5rocks.com</a> insofar as, well, it's HTML5 and slides horizontally! But the key difference is that it's very markup-based - What You See Is What You Need (WYSIWYN) - so creating new slides is easy.</p>

<p>Anyway, I did something similar with TiddlySlides a little while ago, and @FND created a nice Python script to inline external resources - http://mini.softwareas.com/using-fnds-excellent-spapy-to-make-a-single-p. I wanted something slightly different; since this is markup, I can't rely on &lt;img src... pattern. Could have possibly incorporated changes into Fred's SPA, but being that I need it for GDC presentation tomorrow, and I said the last thing to myself the last time I did these slides and it didn't happen, I opted to make a Ruby script which is general-purpose, but meets the specific needs of my slides. See <a href="http://gist.github.com/526114">GIST</a></p>

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

<div class="syntax_hilite"><span class="langName">RUBY:</span><br /><div id="ruby-2">
<div class="ruby"><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:#008000; font-style:italic;">#!/usr/bin/env ruby</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># This script will download all images referenced in URL (URLs ending in</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:#008000; font-style:italic;"># jpg/gif/png), stick them in an images/ directory if they're not already there,</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># and make a new file referencing the local directory.</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:#008000; font-style:italic;">#</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># The script depends on the http://github.com/nahi/httpclient library.</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:#008000; font-style:italic;"># </span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># USAGE</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:#008000; font-style:italic;"># localiseImages.rb index.html</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># ... will create images/ containing images and local.index.html pointing to them.</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:#008000; font-style:italic;">#</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#008000; font-style:italic;"># The point is to cache images so your HTML works offline. See also spa.py</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:#008000; font-style:italic;"># http://mini.softwareas.com/using-fnds-excellent-spapy-to-make-a-single-p</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:#CC0066; font-weight:bold;">require</span> 'httpclient'</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:#008000; font-style:italic;">### UTILITIES</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">IMAGES_DIR = 'images'</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;">Dir.<span style="color:#9900CC;">mkdir</span><span style="color:#006600; font-weight:bold;">&#40;</span>IMAGES_DIR<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> File.<span style="color:#9900CC;">directory</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>IMAGES_DIR<span style="color:#006600; font-weight:bold;">&#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:#9966CC; font-weight:bold;">def</span> filenameize<span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#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; IMAGES_DIR + '/' + url.<span style="color:#CC0066; font-weight:bold;">sub</span><span style="color:#006600; font-weight:bold;">&#40;</span>'http://',''<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#CC0066; font-weight:bold;">gsub</span><span style="color:#006600; font-weight:bold;">&#40;</span>'/','__'<span style="color:#006600; font-weight:bold;">&#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:#9966CC; font-weight:bold;">end</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;"><span style="color:#9966CC; font-weight:bold;">def</span> save<span style="color:#006600; font-weight:bold;">&#40;</span>filename,contents<span style="color:#006600; font-weight:bold;">&#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; file = File.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#996600;">"w"</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; file.<span style="color:#9900CC;">write</span><span style="color:#006600; font-weight:bold;">&#40;</span>contents<span style="color:#006600; font-weight:bold;">&#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; file.<span style="color:#9900CC;">close</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#9966CC; font-weight:bold;">end</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;"><span style="color:#008000; font-style:italic;">### CORE</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:#9966CC; font-weight:bold;">def</span> saveImage<span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#41;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; save<span style="color:#006600; font-weight:bold;">&#40;</span>filenameize<span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#41;</span>, HTTPClient.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">get_content</span><span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#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;"><span style="color:#9966CC; font-weight:bold;">end</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:#9966CC; font-weight:bold;">def</span> extractImages<span style="color:#006600; font-weight:bold;">&#40;</span>filename<span style="color:#006600; font-weight:bold;">&#41;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; contents = File.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>filename, <span style="color:#996600;">"rb"</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">read</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; localContents = <span style="color:#CC0066; font-weight:bold;">String</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>contents<span style="color:#006600; font-weight:bold;">&#41;</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; contents.<span style="color:#9900CC;">scan</span><span style="color:#006600; font-weight:bold;">&#40;</span>/http:\/\/\S+?\.<span style="color:#006600; font-weight:bold;">&#40;</span>?:jpg|gif|png<span style="color:#006600; font-weight:bold;">&#41;</span>/im<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> |url|</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:#CC0066; font-weight:bold;">puts</span> url</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; saveImage<span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> File.<span style="color:#9900CC;">file</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>filenameize<span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#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; localContents.<span style="color:#CC0066; font-weight:bold;">gsub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span>url, filenameize<span style="color:#006600; font-weight:bold;">&#40;</span>url<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#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:#006600; font-weight:bold;">&#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; save<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">"local."</span>+filename, localContents<span style="color:#006600; font-weight:bold;">&#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:#9966CC; font-weight:bold;">end</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;"><span style="color:#008000; font-style:italic;">### COMMAND-LINE</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;">extractImages<span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;color:#800000;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>Aside: This is also related to "offline" web technologies...my article on "Offline" recently went live at HTML5Rocks: <a href="http://www.html5rocks.com/tutorials/offline/whats-offline/">"Offline": What does it mean and why should I care?</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/ruby-script-to-localise-images-for-offline-html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CORS, Scraping, and Microformats</title>
		<link>http://softwareas.com/cors-scraping-and-microformats</link>
		<comments>http://softwareas.com/cors-scraping-and-microformats#comments</comments>
		<pubDate>Tue, 10 Aug 2010 12:42:16 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Microformats]]></category>
		<category><![CDATA[Web Services]]></category>
		<category><![CDATA[XMLHttpRequest]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=942</guid>
		<description><![CDATA[Jump straight to the demo.

Cross-Origin Resource Sharing makes it possible to do arbitrary calls from a web page to any server, if the server consents.  It's a typical HTML5 play: We could do similar things before, but they were with hacks like JSONP. Cross-Origin Resource Sharing lets us can achieve more and do it [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://dl.dropbox.com/u/8429420/experiment/hcard/index.html">Jump straight to the demo.</a></p>

<p><a href="http://www.w3.org/TR/2010/WD-cors-20100727/">Cross-Origin Resource Sharing</a> makes it possible to do arbitrary calls from a web page to any server, if the server consents.  It's a typical HTML5 play: We could do similar things before, but they were with hacks like JSONP. Cross-Origin Resource Sharing lets us can achieve more and do it cleanly. (The same could be said of Canvas/SVG vs drawing with CSS; WebSocket vs XHR-powered Comet; WebWorker vs yielding with setTimeout; Round corners vs 27 different workarounds; and we could go on.)</p>

<p>This has been available for a couple of years now, but I don't see people using it. Well, I haven't checked, but I don't get the impression many sites are offering their content to external websites, despite social media consultants urging them to be "part of the conversation". It's like when people make a gorgeous iPhone app, but their website doesn't work at all in the same phone  (&#42;cough&#42; <a href="http://www.cloudfour.com/iphone-app-store-blinders/">fashionhouse</a>) . Likewise, if you've got a public API, but not providing JSONP/callback support, it's not very useful either...making developers host their own cross-domain proxy is tedious. It's cool there are services like YQL and Embed.ly for some cases, but wouldn't it be better if web pages could just pull in all that external content directly?</p>

<p>Except in this case, it's just not happening. Everyone's offering APIs, but no-ones sharing their content through the web itself. At this point, I should remind you I haven't actually tested my assumption and maybe everyone is serving their public content with "Access-Control-Allow-Origin: *" ... but based on the lack of conversation, I am guessing in the negative. The state of the universe does need further investigation.</p>

<p>Anyway, what's cool about this is you can treat the web as an API. <strong>The Web is my API.</strong> "Scraping a web page" may sound dirtier than "consuming a web service", but it's the cleaner approach in principle. A website sitting in your browser is a perfectly human-readable depiction of a resource your program can get hold of, so it's an API that's self-documenting. The best kind of API. But a whole HTML document is a lot to chew on, so we need to make sure it's structured nicely, and that's where <a href="http://microformats.org">microformats</a> come in, gloriously defining lightweight standards for declaring info in your web page. There's another HTML5 tie-in here, because we now have a similar concept in the standard, <a href="http://diveintohtml5.org/extensibility.html">microdata</a>.</p>

<p><a href="https://dl.dropbox.com/u/8429420/experiment/hcard/index.html">So here's my demo.</a></p>

<p>I went to my homepage at <a href="http://mahemoff.com">mahemoff.com</a>, which is spewed out by a PHP script. I added the following line to the top of the PHP file:</p>

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

<div class="syntax_hilite"><span class="langName">PHP:</span><br /><div id="php-10">
<div class="php"><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:#000000; font-weight:bold;">&lt;?</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; <a href="http://www.php.net/header"><span style="color:#000066;">header</span></a><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#FF0000;">"Access-Control-Allow-Origin: *"</span><span style="color:#006600; font-weight:bold;">&#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; ... <span style="color:#FF9933; font-style:italic;">// the rest of my script</span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color:#000000; font-weight:bold;">?&gt;</span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>Now any web page can pull down "http://mahemoff.com/" with a cross-domain XMLHttpRequest. This is fine for a public web page, but something you should be very careful about if the content is (a) not public; or (b) public but dependent on who's viewing it, because XHR now has a "withCredentials" field that will cause cookies to be passed if it's on. A malicious third-party script could create XHR, set withCredentials to true, and access your site with the user's full credentials. Same situation as we've always had with JSONP, which should also only be used for public data, but now we can be more nuanced (e.g. you <em>can</em> allow trusted sites to do this kind of thing).</p>

<p>On to the client ...</p>

<p>I started out doing a standard XHR, for sanity's sake.</p>

<p><img src="http://farm5.static.flickr.com/4095/4878985954_35f74aa1ea.jpg" /></p>

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

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-11">
<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> 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; xhr.<span style="color: #000066;">open</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"get"</span>, <span style="color: #3366CC;">"message.html"</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; xhr.<span style="color: #000066;">onload</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> <span style="color: #009900; font-style: italic;">//instead of onreadystatechange</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>xhr.<span style="color: #006600;">readyState</span>==<span style="color: #CC0000;color:#800000;">4</span> &amp;&amp; xhr.<span style="color: #000066;">status</span>==<span style="color: #CC0000;color:#800000;">200</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; document.<span style="color: #006600;">querySelector</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"#sameDomain"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">innerHTML</span> = xhr.<span style="color: #006600;">responseText</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; xhr.<span style="color: #006600;">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>Then it gets interesting. The web app makes a cross-domain call using the following facade, which I adapted from a snippet in the veritable Nick Zakas's <a href="http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/">CORS article</a>:</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> get<span style="color: #66cc66;">&#40;</span>url, <span style="color: #000066;">onload</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; <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-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;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"withCredentials"</span> <span style="color: #000066; font-weight: bold;">in</span> xhr<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; xhr.<span style="color: #000066;">open</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"get"</span>, url, <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; <span style="color: #66cc66;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> XDomainRequest != <span style="color: #3366CC;">"undefined"</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; xhr = <span style="color: #003366; font-weight: bold;">new</span> XDomainRequest<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; xhr.<span style="color: #000066;">open</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"get"</span>, url<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> <span style="color: #000066; font-weight: bold;">else</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; xhr = <span style="color: #003366; font-weight: bold;">null</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: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">&#40;</span>xhr<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; xhr.<span style="color: #000066;">onload</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> <span style="color: #000066;">onload</span><span style="color: #66cc66;">&#40;</span>xhr<span style="color: #66cc66;">&#41;</span>; <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; &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-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: #000066; font-weight: bold;">return</span> xhr;</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>This gives us a cross-domain XHR, for any browser that supports the concept, and it makes a request the usual way, and the request works against my site, but not yours, because of the header I set earlier on my site. Now I can dump that external content in a div:</p>

<p><img src="http://farm5.static.flickr.com/4114/4878413271_d09c4f2497_z.jpg" /></p>

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

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-13">
<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;">get<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"http://mahemoff.com/"</span>, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>xhr<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; document.<span style="color: #006600;">querySelector</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"#crossDomain"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">innerHTML</span> = xhr.<span style="color: #006600;">responseText</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></ol></div>
</div></div>

<p><br /></p>

<p>(This would be a monumentally thick thing to do if you didn't trust the source, as it could contain script tags with malicious content, or a phishing form. Normally, you'd want to sanitise or parse the content first. In any event, I'm only showing the whole thing here for demo purposes.)</p>

<p>Now comes the fun part: Parsing the content that came back from an external domain. It so happens that I have embedded hCard microformat content at http://mahemoff.com. It's in the expandable business card you see on the top-left:</p>

<p><a href="http://mahemoff.com"><img src="http://farm5.static.flickr.com/4136/4878996726_cc4ebbf185_t.jpg"/></a></p>

<p>And the hCard content looks like this, based on :</p>

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

<div class="syntax_hilite"><span class="langName">HTML:</span><br /><div id="html-14">
<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/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"card"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"vcard"</span><span style="color: #000000; font-weight: bold;">&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"fn"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Michael<span style="color: #ddbb00;">&amp;nbsp;</span>Mahemoff<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/img.html"><span style="color: #000000; font-weight: bold;">&lt;img</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"photo"</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">"http://mahemoff.com/speak2.jpg"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/img&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"role"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>&quot;I like to make the web better and sushi&quot;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"adr"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>London, UK<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"geo"</span><span style="color: #000000; font-weight: bold;">&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/abbr.html"><span style="color: #000000; font-weight: bold;">&lt;abbr</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"latitude"</span> <span style="color: #000066;">title</span>=<span style="color: #ff0000;">"51.32"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>51<span style="color: #ddbb00;">&amp;deg;</span>32<span style="color: #ddbb00;">&amp;#39;</span>N<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/abbr&gt;</span></span>,&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><a href="http://december.com/html/4/element/abbr.html"><span style="color: #000000; font-weight: bold;">&lt;abbr</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"longitude"</span> <span style="color: #000066;">title</span>=<span style="color: #ff0000;">"0"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>0<span style="color: #ddbb00;">&amp;deg;</span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/abbr&gt;</span></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: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span>&nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"email"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>michael@mahemoff.com<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"vcardlinks"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">"me"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"url"</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"http://mahemoff.com"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>homepage<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></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: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">"me"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"url"</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"http://twitter.com/mahmoff"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>twitter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>&nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/a.html"><span style="color: #000000; font-weight: bold;">&lt;a</span></a> <span style="color: #000066;">rel</span>=<span style="color: #ff0000;">"me"</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"url"</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">"http://plancast.com/mahemoff"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>plancast<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></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: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span> </div></li></ol></div>
</div></div>

<p><br /></p>

<p>It's based on the <a href="http://microformats.org/wiki/hcard">hCard microformat</a>, which really just tells you what to call your CSS classes...I told you microformats were lightweight! The whole idea of the card comes from Paul Downey's genius <a href="http://blog.whatfettle.com/2010/01/14/hardboiled-hcards/">Hardboiled hCards</a> project.</p>

<p>Anyway, bottom line is we've just extracted some content with hCard data in it, so it should be easy to parse it in a standard way and make sense of the content. So I start looking for a hCard Javascript library and find one, that's the beauty of standards. Even better, it's called <a href="http://www.danwebb.net/2007/2/9/sumo-a-generic-microformats-parser-for-javascript">Sumo</a> and it comes from Dan Webb.</p>

<p>The hCard library expects a DOM element containing the hCard(s), so I pluck that from the content I've just inserted on the page, and pass that to the library. Then it's a matter of using the "hCard" object to render a custom UI:</p>

<p><img src="http://farm5.static.flickr.com/4078/4879071706_806f389a5b.jpg"/></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;"><span style="color: #003366; font-weight: bold;">var</span> hcard = HCard.<span style="color: #006600;">discover</span><span style="color: #66cc66;">&#40;</span>document.<span style="color: #006600;">querySelector</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"#crossDomain"</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;color:#800000;">0</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: #003366; font-weight: bold;">var</span> latlong = <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #006600;">maps</span>.<span style="color: #006600;">LatLng</span><span style="color: #66cc66;">&#40;</span>parseInt<span style="color: #66cc66;">&#40;</span>hcard.<span style="color: #006600;">geo</span>.<span style="color: #006600;">latitude</span><span style="color: #66cc66;">&#41;</span>, parseInt<span style="color: #66cc66;">&#40;</span>hcard.<span style="color: #006600;">geo</span>.<span style="color: #006600;">longitude</span><span style="color: #66cc66;">&#41;</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; <span style="color: #003366; font-weight: bold;">var</span> markerImage = <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #006600;">maps</span>.<span style="color: #006600;">MarkerImage</span><span style="color: #66cc66;">&#40;</span>hcard.<span style="color: #006600;">photoList</span><span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;color:#800000;">0</span><span style="color: #66cc66;">&#93;</span>, <span style="color: #003366; font-weight: bold;">null</span>, <span style="color: #003366; font-weight: bold;">null</span>, <span style="color: #003366; font-weight: bold;">null</span>, <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #006600;">maps</span>.<span style="color: #006600;">Size</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;color:#800000;">40</span>, <span style="color: #CC0000;color:#800000;">40</span><span style="color: #66cc66;">&#41;</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> infoWindow = <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #006600;">maps</span>.<span style="color: #006600;">InfoWindow</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span>content: <span style="color: #3366CC;">"&lt;a href='"</span>+hcard.<span style="color: #006600;">urlList</span><span style="color: #66cc66;">&#91;</span><span style="color: #CC0000;color:#800000;">0</span><span style="color: #66cc66;">&#93;</span>+<span style="color: #3366CC;">"'&gt;"</span>+hcard.<span style="color: #006600;">fn</span>+<span style="color: #3366CC;">"&lt;/a&gt;"</span>, pixelOffset: <span style="color: #003366; font-weight: bold;">new</span> google.<span style="color: #006600;">maps</span>.<span style="color: #006600;">Size</span><span style="color: #66cc66;">&#40;</span><span style="color: #CC0000;color:#800000;">0</span>,-<span style="color: #CC0000;color:#800000;">20</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#125;</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;... </div></li></ol></div>
</div></div>

<p><br /></p>

<p>And I also dump the entire hCard for demo purposes, using James Padolsey's <a href="http://james.padolsey.com/javascript/prettyprint-for-javascript/">PrettyPrint</a>.</p>

<p><img src="http://farm5.static.flickr.com/4123/4879071986_45ab3ce235.jpg"/></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;">document.<span style="color: #006600;">querySelector</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"#hcardInfo"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">appendChild</span><span style="color: #66cc66;">&#40;</span>prettyPrint<span style="color: #66cc66;">&#40;</span>hcard<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>There's lots more fun to be had with the Web as an API. According to <a href="http://microformats.org/">the microformats blog</a>, 2 million web pages now have embedded hCards. Offer that content to the HTML5 mashers of the world and they will make beautiful things.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/cors-scraping-and-microformats/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A jQuery Inheritance Experiment</title>
		<link>http://softwareas.com/a-jquery-inheritance-experiment</link>
		<comments>http://softwareas.com/a-jquery-inheritance-experiment#comments</comments>
		<pubDate>Mon, 09 Aug 2010 01:18:54 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JQuery]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=938</guid>
		<description><![CDATA[I like jQuery a lot, but I often find myself re-doing my way of OO and inheritance each time I start a new app. And so, I just did it again of course.

I was starting to write a lame HTML5 game, where you have "AlienModels" (of the MVC, not Star Trek, variety), and each with [...]]]></description>
			<content:encoded><![CDATA[<p>I <a href="http://softwareas.com/tag/jquery">like jQuery a lot</a>, but I often find myself <a href="http://softwareas.com/automagic-event-registration">re-doing my way of OO</a> and inheritance each time I start a new app. And so, I just did it again of course.</p>

<p>I was starting to write a lame HTML5 game, where you have "AlienModels" (of the MVC, not Star Trek, variety), and each with their own "AlienView". When an AlienModel enter()s, its view will detect a "enter" event and show the alien entering the scene. Certain types of aliens will fly in, certain aliens will fade in, and so on. I started creating an AlienView abstraction, but I figured this is something jQuery can do for me. An AlienView might simply be a jQuery selector. However, this is where jQuery reaches its limits, as I want to call $("someAlienView").enter(50,50), and to have the alien's entry towards co-ordinate (50,50) animated, but animated differently depending on what kind of alien it is.</p>

<p>So I created a framework to do this. <a href="http://jsdo.it/mahemoff/yvOL/fullscreen">Code and Demo here.</a></p>

<p>The usage is this:</p>

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

<div class="syntax_hilite"><span class="langName">HTML:</span><br /><div id="html-19">
<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/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"shy guy"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>shy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;"><span style="color: #009900;"><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">&lt;div</span></a> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">"fly guy"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>fly<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div&gt;</span></span> </div></li></ol></div>
</div></div>

<p><br /></p>

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

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-20">
<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;">".shy"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">define</span><span style="color: #66cc66;">&#40;</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; disappear: <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> $<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">slideUp</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; <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: #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; &nbsp; $<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">".fly"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">define</span><span style="color: #66cc66;">&#40;</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; disappear: <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; &nbsp; &nbsp; $<span style="color: #66cc66;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fadeOut</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fadeIn</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fadeOut</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fadeIn</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fadeOut</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">fadeIn</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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.<span style="color: #006600;">animate</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span>top: -<span style="color: #CC0000;color:#800000;">200</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">hide</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; <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: #66cc66;">&#125;</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;</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: #3366CC;">".guy"</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">disappear</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>; </div></li></ol></div>
</div></div>

<p><br /></p>

<p>When we call $(".guy").disappear(), what happens depends on whether this is a ".shy" or a ".fly". This is basic polymorphism, which jQuery lacks. The $.fn.define() plugin I wrote (see the code in that example) shoehorns it in, but maybe that's not a good idea...I'm making jQuery into something it's not. So on IRC someone pointed me to <a href="http://ryanflorence.com/object-oriented-jquery-with-mootools-pigs-take-flight/">this MooTools-jQuery article</a>. I need to read that article. I also need to get into MooTools, which I think may be more appropriate for this kind of thing, with its unashamed use of prototype (afaict). In general, my urge for more OO and scalable architecture tells me I need to look further afield than jQuery. But syntactic sugar trumps all, so I'll only go elsewhere if it doesn't smell of enterprisey, false sense of security, <a href="http://www.youtube.com/watch?v=5kj5ApnhPAE">public static void</a>ness.</p>

<p>Incidentally $.fn.define() could go further than I currently have it; it would be possible to set up an inheritance chain, where you could define $(".guy").disappear() explicitly, so that if an element matched ".guy"  but not ".shy" or ".fly", it would follow the ".guy" rule. (But not the other way round.) I probably won't though.</p>

<p>Incidentally (2), thanks @agektmr for telling me about <a href="http://jsdo.it">jsdo.it</a>, a mostly-Japanese Javascript pastebin similar toas <a href="http://jsbin.com">jsBin</a> and <a href="http://jsFiddle.net">jsFiddle</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/a-jquery-inheritance-experiment/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Tragedy and Triumph of Podcasts</title>
		<link>http://softwareas.com/the-tragedy-and-triumph-of-podcasts</link>
		<comments>http://softwareas.com/the-tragedy-and-triumph-of-podcasts#comments</comments>
		<pubDate>Sun, 08 Aug 2010 09:36:37 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[HumansAndTech]]></category>
		<category><![CDATA[Podcasting]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=936</guid>
		<description><![CDATA[It's now about 6 years since I discovered podcasts while listening to a pre-podcast podcast, The Gillmor Gang. It's everything I ever wanted from radio talkback - niche topics, on-demand listening, access anywhere, rich metadata, and no music - I've chosen to listen to talkback for a reason (Hello Australian Broadcasting Corporation).

A perfect storm of [...]]]></description>
			<content:encoded><![CDATA[<p>It's now about 6 years since I discovered podcasts while listening to a pre-podcast podcast, The Gillmor Gang. It's everything I ever wanted from radio talkback - niche topics, on-demand listening, access anywhere, rich metadata, and no music - I've chosen to listen to talkback for a reason (Hello Australian Broadcasting Corporation).</p>

<p>A perfect storm of iPods, massive bandwidth, and feed religion made podcasts possible, and they are still going on strong. However, they've never taken off in the mainstream, and you can't say they haven't had a fair chance. Apple's inclusion of podcasts in iTunes and iOS makes them pretty darn accsessible if people want them, yet many people aren't using them. Having informally surveyed a few people, I've found they aren't actually aware how easy iTunes made it to subscribe to podcasts, so there's more work to be done there. But I think if there was enough word-of-mouth publicity, people would be using it to subscribe. It's not harder than uploading photos for example. (I do have <a href="http://softwareas.com/seven-things-about-itunes-that-are-just-plain-wrong">many reservations</a> about iTunes, but those are more for advanced users.)</p>

<p>Podcasts haven't taken off in much the same was as RSS and feeds and news readers have never taken off. Or have they? I recently heard Jon Udell speaking on the topic (on a podcast-or-other, not his own one) and he made the point that we expected everyone would wake up in the morning and open up their reader of feeds they'd subscribed to. Didn't happen. But feeds did happen, social feeds, in the form of Facebook, Twitter, FourSquare, Buzz, and so on. Anyway, those don't really translate to podcasts, not yet anyway. If <a href="http://huffduffer.com/">Huffduffer</a> let you subscribe to all your friends' feeds, it <i>would</i> be possible, at least in a geeky niche community anyway.</p>

<p>My main point here is to highlight a few things that haven't happened for podcasts, and would make them better and just a bit more popular if they did. I'm not arguing these things would make podcasts wildly popular; consider this mostly a wishlist and some pointers to a few trends:</p>

<p><strong>Hardware:</strong> So we have these networked devices right? The most prominent at this time being iPhone and iPad, but they still don't sync over the cloud. Using Android recently, I've come to appreciate how nice it is to sync podcasts in the background, over the air. Latest podcasts are just there. Downside being, you have to use an expensive phone, which is a problem for gym and running, and also a drain on that precious battery life. While in the US, I recently picked up an <a href="http://www.amazon.com/Ibiza-H1B008AQ-Rhapsody-Personal-Player/dp/B001BJCR7I/ref=sr_1_1?s=electronics&#038;ie=UTF8&#038;qid=1281258111&#038;sr=1-1">Ibiza Rhapsody player</a>, a bargain at $44 for an 8GB player which automatically connects and syncs. Would be even better if I could sign up to the Rhapsody service in the UK, but not gonna happen. The neat thing is it has podcasts built in, and lets me sync them over the fly. Downside is it doesn't have a keyboard, so if I want a feed not in the default list, I have to type it manually using the one-at-a-time, left-right-left-right, character entry. Now I've been waiting for someone to release a mini Android device, so I was blitzkrieged to hear <a href="http://twit.tv/twig54">This Week In Google</a> mention a new line of <a href="http://phandroid.com/2010/08/04/archos-gen-8-tablet-3-2-inch-variant-specs-leaked/">Archos "tablets"</a>, including a 3.2" device. Which will be perfect for gym and running, allowing me to switch between podcasts and Spotify, with both of those things syncing over the air, and at $150, cheap enough to risk overzealous destruction <img src='http://softwareas.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Can you say Drool.</p>

<p><img src="http://picupper.com/2010/08/08/archos-tablets.jpg" /></p>

<p><strong>Cloud OPML:</strong> It's awesome we have a standard like OPML, a simple way to declare a list of feeds, AKA <a href="http://nick.typepad.com/blog/2005/10/reading_lists_f.html">Reading Lists</a>. (Technically, reading lists are a subset of OPML, but OPML is the term commonly used, so I'll keep using it here.) However, in both podcast and feedreader world, there's an extremely weird tendency to assume OPML lives on your hard drive. Many newsreaders and podcatchers allow you to import and export to and from OPML...but they assume OPML lives on your hard drive, not in the cloud!!! Why? I have no idea. The whole concept is inherently cloud, so it makes no sense. I just want to stick my list of podcasts on a server somewhere, and when I start using a new client, it downloads them for me. As a consequence, I've manually entered my subscriptions dozens of times over the years. This is especially important for mobile devices - especially ones without a keyboard - like the Rhapsody player I mentioned above. <b>Podcatcher/Feed-reader developers, I urge you to pull down subscriptions from OPML resources in the sky...and to offer users the ability to publish their subscriptions that way too!</b></p>

<p><strong>Archives:</strong> Sadly, podcasts don't live on the same way blog post do. This is sad because many podcasts are reference material, not just latest news. Take a podcast like the excellent <a href="http://www.summahistorica.com/">History According to Bob</a>. Over the years, he's produced hundreds of fine recordings on all manner of ancient and recent history. But subscribe to his podcast, and you'll only be able to backtrack 8 episodes. Now I chose Bob as an example because he actually offers older podcasts <a href="http://www.summahistorica.com/order.htm">for DVD purchase</a>, but most podcasters would be fine to let people get hold of old podcasts; they just have no way to actually make it practical. History is not the only topic; there are podcasts about movies, science, economics, software engineering...where a 2004 podcast would be just as relevant today, if only you could get hold of it. Some podcasts include every single episode in the feed, but then certain clients will end up pulling down gigabytes of data when each user subscribes. As a user, your best best is to scour archives - if they exist - and use something like huffduffer to aggregate them. But that's still painful and not something every user will do. Odeo was on the right track, by building up a long list of all podcasts ever produced on each feed, whether in the current feed or not. But Odeo spawned Twitter and Odeo sadly isn't.</p>

<p><strong>Integrate with Music Players:</strong> Call it, "if you can't beat them, join them", but I would love to see the music services embrace podcasts. Spotify, for example, has a great interface for choosing songs on the fly as well as subscribing to playlists; it could easily be extended to podcasts to become a one-stop-shop for your listening needs. <a href="http://www.playdio.com/">Playdio</a> is an interesting move in this direction, allowing people to record talk tracks in between music tracks,  and their <a href="http://www.playdio.com/contact">contact form</a> mentions podcasts, so maybe there is hope. Still, I wish Spotify et al would just bake podcasts into the player and be done with it. And considering the social features these things are starting to have, it could actually be quite powerful.</p>

<p><strong>Social: </strong> There's not really much you can do to find out what friends are listening to and all that cal. There's <a href="http://www.amigofish.com/">Amigofish</a>, but it would be nice to see it baked into the players directly.</p>

<p>True, music will probably be in first place for the foreseeable future, mirroring reality, but its needs have already been met, much more so than talk formats, where there really hasn't been much innovation since 2004.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/the-tragedy-and-triumph-of-podcasts/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Javascript WTFe3</title>
		<link>http://softwareas.com/javascript-wtfe3</link>
		<comments>http://softwareas.com/javascript-wtfe3#comments</comments>
		<pubDate>Wed, 04 Aug 2010 22:16:58 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[wtfjs]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=931</guid>
		<description><![CDATA[
&#62; parseInt(1000)
1000
&#62; parseInt(1000.0)
1000
&#62; parseInt("1000.0")
1000
&#62; parseInt(1e3)
1000
&#62; parseInt("1e3")
1


WTFJS

So how to actually parse it with Javascript built-in? Spoiler alert - select the following white text:



parseInt(parseFloat("1e3"))



(Thanks @CAIndy)
]]></description>
			<content:encoded><![CDATA[<p><pre>
&gt; parseInt(1000)
1000
&gt; parseInt(1000.0)
1000
&gt; parseInt("1000.0")
1000
&gt; parseInt(1e3)
1000
&gt; parseInt("1e3")
1
</pre></p>

<p><a href="http://wtfjs.com/">WTFJS</a></p>

<p>So how to actually parse it with Javascript built-in? Spoiler alert - select the following white text:</p>

<hr />

<p><span style="color:white">parseInt(parseFloat("1e3"))</span></p>

<hr />

<p>(Thanks @CAIndy)</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/javascript-wtfe3/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Letters from a Gaming Newbie</title>
		<link>http://softwareas.com/letters-from-a-gaming-newbie</link>
		<comments>http://softwareas.com/letters-from-a-gaming-newbie#comments</comments>
		<pubDate>Mon, 26 Jul 2010 16:51:52 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Conference]]></category>
		<category><![CDATA[Games]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[Web]]></category>

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

I was pleased to attend Casual Connect this week and talked about how HTML5 is becoming viable for games development, alongside my colleague Mark, who covered the Chrome Web Store in general. I was definitively there in a purely web geek capacity, as gaming is not an industry I'm very familiar with. So here are [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://picupper.com/2010/07/24/noobs-ydc.jpg" /></p>

<p>I was pleased to attend Casual Connect this week and talked about how HTML5 is becoming viable for games development, alongside my colleague <a href="http://www.satori.org">Mark</a>, who covered the Chrome Web Store in general. I was definitively there in a purely web geek capacity, as gaming is not an industry I'm very familiar with. So here are a few things I learned:</p>

<ul>
  <li>Casual gaming is quite distinct from "hardcore" gaming. (as @Eastmad reminded me on Twitter.)</li>
  <li>Casual gaming is heavily intertwined with "social" gaming these days - games on Facebook et al.</li>
  <li>The social network is just "the graph". At least for some games, they're architected to separate "the graph" from the core game logic, so you can swap in and out different social networks. The graph is of course essential for gameplay with social games as well as viral adoption.</li>
  <li>The industry is mature - there is a clear ecosystem of companies with different roles. Studios make games, publishers distribute them, portals aggregate them, social networks provide the graph. And then there are ad networks, analytics, hosts/caches, development tools, virtual currency providers, consultants. (Very cool seeing how any vertical quickly evolves into a distinct industry structure. Adam Smith approves.)</li>
  <li>The industry is sophisticated. There is a big aspect of number-crunching, analytics-driven, thinking, e.g. pinning down the cost of customer acquisition. There's a feeling that monetization is the best growth opportunity right now, more so than increasing the number of players. 1-2% of people spend, whereas with Massive Multiplayer Online games and in Asian markets, 5-10% is more common.</li>
  <li>Trends to watch: Streaming games (Gaikai, Onlive) - It's amazing it actually works, but these are technologies that treat the user's computer/browser as a dumb terminal and stream the game's video down to them; location based games, merging real and virtual worlds; embedding games into the fabric of the web (e.g. through widgets etc), so they're not just isolated in social network sites and dedicated game portals; combining genres, so that hardcore gamers can interact with their casual gamer friends; using multiple channels in clever ways, rather than just porting the same game to ten different platforms.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/letters-from-a-gaming-newbie/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thinking in Web Apps</title>
		<link>http://softwareas.com/thinking-in-web-apps</link>
		<comments>http://softwareas.com/thinking-in-web-apps#comments</comments>
		<pubDate>Sat, 24 Jul 2010 21:21:06 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[Patterns]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=925</guid>
		<description><![CDATA[Thinking In Web Apps is a short list of design principles for Chrome Web apps, published a couple of weeks ago by several of us in Chrome Developer Relations.

Many people think Developer Relations means blogging and speaking. That's part of it, but it's also important to be spending time with developers and understanding the challenges [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/chrome/apps/articles/thinking_in_web_apps.html">Thinking In Web Apps</a> is a short list of design principles for Chrome Web apps, published a couple of weeks ago by several of us in Chrome Developer Relations.</p>

<p>Many people think Developer Relations means blogging and speaking. That's part of it, but it's also important to be spending time with developers and understanding the challenges they face, as well as supporting them. In the case of Chrome Web Store, I've been working with several partners who are building apps in time for the store's launch. Explaining how certain technologies work and taking questions back to the core Chrome development team. One of the things I've discovered in Developer Relations is the way patterns/principles emerge:</p>

<ul>
<li>A new capability is announced, e.g. a new programming language, an upgrade to a hosting service, a new API. In this case, it's the Chrome Web Store and the concept of installable web apps.</li>
<li>We make some guesses about how to use it and share them with developers. You have to see it as educated guesses; it's the law of unanticipated consequences that says you can never be sure how people will use a capability, even if you're the one who designed it.</li>
<li>Developers start to build use the new capability.</li>
<li>By aggregating across all of the pioneering developers, and talking to other developer relations people working with other pioneering developers, we gain a new appreciation of what works and what doesn't.</li>
<li>We have more general info to share with partners. Wash, rinse, repeat.</li>
</ul>

<p>The important thing is to be documenting what we're learning as we go along, hence you can expect to see more articles like Thinking in Web Apps. Whether you want to call them patterns, principles, or whatever.</p>

<p>See also <a href="http://www.interaction-design.org/encyclopedia/task_artifact_cycle.html">Task-Artifact Cycle</a>.</p>

<p><img src="http://picupper.com/2010/07/24/task_artifact_cycle.gif" /></p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/thinking-in-web-apps/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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-25"><a href="#" onclick="javascript:showPlainTxt('javascript-25'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-25">
<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-26"><a href="#" onclick="javascript:showPlainTxt('javascript-26'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-26">
<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-27"><a href="#" onclick="javascript:showPlainTxt('javascript-27'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-27">
<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-28"><a href="#" onclick="javascript:showPlainTxt('javascript-28'); return false;">PLAIN TEXT</a></span></div>

<div class="syntax_hilite"><span class="langName">JAVASCRIPT:</span><br /><div id="javascript-28">
<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>
	</channel>
</rss>
