<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Software As She's Developed &#187; Project</title>
	<atom:link href="http://softwareas.com/tag/project/feed" rel="self" type="application/rss+xml" />
	<link>http://softwareas.com</link>
	<description>Mahemoff's Podcast/Blog - Web, Programming, Usability from the Author of 'Ajax Design Patterns' (AjaxPatterns.org)</description>
	<lastBuildDate>Mon, 26 Jul 2010 16:52:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- podcast_generator="podPress/8.8" - maintenance_release="8.8.4" -->
		<copyright>Copyright &amp;#xA9; Software As She's Developed 2010 </copyright>
		<managingEditor>michael@mahemoff.com (Software As She's Developed)</managingEditor>
		<webMaster>michael@mahemoff.com (Software As She's Developed)</webMaster>
		<category>posts</category>
		<ttl>1440</ttl>
		<itunes:keywords></itunes:keywords>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary>Mahemoff's Podcast/Blog - Web, Programming, Usability from the Author of 'Ajax Design Patterns' (AjaxPatterns.org)</itunes:summary>
		<itunes:author>Software As She's Developed</itunes:author>
		<itunes:category text="Society &amp; Culture"/>
		<itunes:owner>
			<itunes:name>Software As She's Developed</itunes:name>
			<itunes:email>michael@mahemoff.com</itunes:email>
		</itunes:owner>
		<itunes:block>No</itunes:block>
		<itunes:explicit>no</itunes:explicit>
		<itunes:image href="http://softwareas.com/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<image>
			<url>http://softwareas.com/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
			<title>Software As She's Developed</title>
			<link>http://softwareas.com</link>
			<width>144</width>
			<height>144</height>
		</image>
		<item>
		<title>Yoink: Extracting All Scripts and Stylesheets on the Page</title>
		<link>http://softwareas.com/yoink-extracting-all-scripts-and-stylesheets-on-the-page</link>
		<comments>http://softwareas.com/yoink-extracting-all-scripts-and-stylesheets-on-the-page#comments</comments>
		<pubDate>Mon, 26 Apr 2010 00:14:43 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[yoink]]></category>

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

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

PLAIN TEXT

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




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

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

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

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

<p><br /></p>

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

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

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

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

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

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

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

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

<p><br /></p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/yoink-extracting-all-scripts-and-stylesheets-on-the-page/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WebWait Updated</title>
		<link>http://softwareas.com/webwait-updated</link>
		<comments>http://softwareas.com/webwait-updated#comments</comments>
		<pubDate>Wed, 14 Apr 2010 01:59:36 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WebWait]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=842</guid>
		<description><![CDATA[One of the projects I wanted to work on in my time off was WebWait.

It finally does what I wanted it to do all along: Permanently record benchmarks. You can get a unique URL for each benchmarking session you run by hitting Save. Funny - WebWait was running as a Rails app for several years, [...]]]></description>
			<content:encoded><![CDATA[<p>One of the projects I wanted to work on in my time off was <a href="http://webwait.com">WebWait</a>.</p>

<p>It finally does what I wanted it to do all along: Permanently record benchmarks. You can get a unique URL for each benchmarking session you run by hitting Save. Funny - WebWait was running as a Rails app for several years, but was always a pure browser-side client until I finally completed this. (Ultimately, I didn't use Rails anyway - see below.)</p>

<p><a href="http://webwait.com/1"><img src="http://farm5.static.flickr.com/4068/4519047329_58666b6d67_o.jpg" /></a></p>

<p>Some other enhancements too ...</p>

<ul>
<li>Bar charts (using the Google Charts API):</li>
</ul>

<p><img src="http://farm5.static.flickr.com/4028/4519684544_3354338700.jpg" /></p>

<ul>
<li>Expanded dashboard, showing a box for each site you've trialled. (Previously, there was only one box ever shown, the latest one. Since people like taking screenshots of these, I figured it would be cool to include multiple boxes.)</li>
</ul>

<p><img src="http://farm5.static.flickr.com/4008/4519683900_259ed0cd8e_o.jpg" /></p>

<ul>
<li>There is also <a href="http://webwait.com/1.json">a JSON view</a> of the trials that were recorded.</li>
</ul>

<p>It would be cool to expand it further, for example allowing pages to be cross-linked when they benchmark the same trial. But I'll leave it here and see where demand takes it.</p>

<p>The new WebWait server is powered by the incredibly productive trio of Ruby, Sinatra, and TokyoCabinet. On the browser, it's still jQuery, with the <a href="http://datatables.net/">DataTables plugin</a> and my own <a href="http://github.com/mahemoff/jQuery-iFrame">jQuery iFrame plugin</a>.
Hosted on SliceHost (where I have now <a href="http://mini.softwareas.com/techscribbles-ubuntu-sysadmin-tasks-for-webse">happily migrated many things</a>.)</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/webwait-updated/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>InfoBoxPlugin: A TiddlyWiki Plugin for InfoBoxen</title>
		<link>http://softwareas.com/infoboxplugin</link>
		<comments>http://softwareas.com/infoboxplugin#comments</comments>
		<pubDate>Wed, 07 Oct 2009 02:04:12 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Osmosoft]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[TiddlyWiki]]></category>

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

G'Day, here's a new tiddlywiki plugin I've been working on: InfoBoxPlugin. It's based on the equally-monikered infoBox in MediaWiki/Wikipedia, which you'll see in any article that is marked "current event" or "controversial", for example, on the big W. I find infoBoxes elegant, as they are unobtrusive enough to let you get on reading the article, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/37184970@N00/3988151619/" title="InfoBoxPlugin - Lists tiddlers in a table (by mahemoff)"><img src="http://farm4.static.flickr.com/3515/3988151619_77bfa158d4.jpg" title="InfoBoxPlugin - Lists tiddlers in a table (by mahemoff)" alt="InfoBoxPlugin - Lists tiddlers in a table (by mahemoff)" width="400" height="627" /></a></p>

<p>G'Day, here's a new tiddlywiki plugin I've been working on: <a href="http://tiddlywiki.mahemoff.com/InfoBoxPlugin.html">InfoBoxPlugin</a>. It's based on the equally-monikered infoBox in MediaWiki/Wikipedia, which you'll see in any article that is marked "current event" or "controversial", for example, on the big W. I find infoBoxes elegant, as they are unobtrusive enough to let you get on reading the article, and are easily ignored in the same way as <a href="http://www.useit.com/alertbox/banner-blindness.html">web ads</a>, but when you do focus on them, they are clear in meaning and support pattern recognition, with each type of infoBox having its own look and distinct icon.</p>

<p>The infoBox macro makes infoBoxen that look as shown in the diagram above. In the simplest case, you type this into a tiddler:</p>

<p>&lt;&lt;infoBox&gt;&gt;This is good stuff - pay attention mkay.&gt;&gt;</p>

<p>Pretty straightforward. One funniness here is the bracket asymmetry. We're trying to do something similar to XML tags, what with their start tag and attribs, followed by body, followed by closing tag, so you'd expect to see:</p>

<p>&lt;&lt;infoBox&gt;&gt;This is good stuff - pay attention mkay.&lt;&lt;/infoBox&gt;&gt;</p>

<p>or sumptink like dat. But one of my lessons was that tiddlywiki has a somewhat unusual convention, enshrined only in the gradient macro to my knowledge, for the former syntax. The only way to do something else would be to refactor or replicate or hijack the core code, and I don't fancy it, and in any event it would go against the standard already set by gradient. In any event, I was pleased enough when Jeremy showed me the example of the gradient tag, which shows that this kind of "macro body" is even possible, so I settled with that.</p>

<p>Okay, so that's nice, you can do a simple message, but where it gets more to the point is where you build up a family of infoBox types for your TiddlyWiki, each having a separate definition tiddler. For example, you will often want a "warning" infoBox to appear in various places. So you make a "warningInfoBox" tiddler, with the following text:</p>

<p><pre>
|background|#fdd|
|borderColor|#f66|
|headingColor|#800|
|heading|Danger, Will Robinson!!!|
|messageFontStyle|normal|
|messageColor|#900|
|message|Please follow these instructions carefully.|
|iconURL|icons##stop|
|iconWidth|40|
</pre></p>

<p>And then in a tiddler, you just write &lt;&lt;infoBox warning&gt;&gt;&gt;&gt; The association between "warning" and "warningInfoBox" is an enforced convention; my macro just appends "InfoBox" to the type you declare. The double-double closing bracket is a consequence of what I said above, combined with the fact that the definition has a pre-defined "message". This is often going to be what we want, but not always. In fact, all of the fields above are optional, so you could leave out "message" and then the warning macro would have to specify it (if you wanted a message, that is). i.e. &lt;&lt;infoBox warning&gt;&gt;This Is Serious Mum.&gt;&gt; (... because the undeniably-talented, always-controversial, Aussie band This Is Serious Mum - aka TISM - popped into my head as an instructive example for this warning.)</p>

<h3>Some other things to say</h3>

<ul>
<li>This plugin is part of a greater effort to pull out the goodies from TiddlyGuv into reusable modules. TiddlyGuv was the first thing I worked on upon joining Osmosoft, and when I looked it at with fresh eyes recently, I realised how much of what I built is just generic TiddlyWiki functionality. I now have a better understanding of what makes an independent TiddlyWiki plugin, and indeed I have a much greater respect for the whole modularity concept in TiddlyWiki, because it really satisfies all the traditional software engineering principles of encapsulation, orthogonality, etc etc in a neat bite-size way, which I will have to explain more about elsewhere. infoBox is the first of several plugins that need to be exorcised from the TiddlyGuv base.</li>
<li>The "macro body" thing is actually quite easy - you just call <tt>wikifier.subWikify(domEl, "&gt;&gt;");</tt> where domEl is some DOM element. This will keep reading from the end of the macro definition to the next occurrence of &gt;&gt;, and fill domEl with the results of wikifying that content. It would be nice if there was a function to let you just get the string, instead of sticking it in the DOM, but you could still achieve that yourself by shoving it into a hidden element and capturing its innerHTML. The only complication for me was a common one these days of jumping between JQuery-land and traditional DOM-land, since TiddlyWiki now ships with JQuery, but much of the infrastructure has not (yet) been retrofitted to talk JQuery. Once I did a JQuery-to-DOM conversion, it worked fine.</li>
<li>Another interesting detour that happened here concerned cross-referencing tiddlers. Something you will want often want to do with infoBoxes is use icons. In a single-file TiddlyWiki, often intended to be offline, the icons would need to be data: URIs. This applies to other plugins too, so I dedcided to look into it a bit. I wanted a way for the "iconURL" slice in the InfoBox definition to either be a regular URL, or a reference to another tiddler containing the data: URI, so as to isolate it away. This led me to learn more about <a href="http://groups.google.com/group/tiddlywikidev/browse_thread/thread/91e2b4bdc82cb8bd">transclusion</a>. With thanks to @FND, and after some experimentation, I found the easiest way was to support linking to sections of another tiddler. See how it works in <a href="http://tiddlywiki.mahemoff.com/InfoBoxPlugin.html">the demo tiddlywiki</a>, where an "icons" tiddler contains the data:URI icons.</li>
</ul>

<p>Wow, I didn't expect to say so much about what is not a major plugin. It comes at a time when I've been making some realisations about tiddlywiki, hence the verbeage.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/infoboxplugin/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SimpleMessagePlugin: Unobtrusive TiddlyWiki Status Message</title>
		<link>http://softwareas.com/simplemessageplugin-unobtrusive-tiddlywiki-status-message</link>
		<comments>http://softwareas.com/simplemessageplugin-unobtrusive-tiddlywiki-status-message#comments</comments>
		<pubDate>Sat, 03 Oct 2009 00:06:27 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Osmosoft]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[TiddlyWiki]]></category>

		<guid isPermaLink="false">http://softwareas.com/simplemessageplugin-unobtrusive-tiddlywiki-status-message</guid>
		<description><![CDATA[To simplify TiddlyGuv message rendering, I made "SimpleMessagePlugin". It removes the message box 1 second after a message was shown (using displayMessage). In the event another message appears in that time, it appends the message (as it normally does) and extends the message box's lifetime by a second. In other words, it always closes a [...]]]></description>
			<content:encoded><![CDATA[<p>To simplify TiddlyGuv message rendering, I made "SimpleMessagePlugin". It removes the message box 1 second after a message was shown (using displayMessage). In the event another message appears in that time, it appends the message (as it normally does) and extends the message box's lifetime by a second. In other words, it always closes a second after the last message was shown. The algorithm is a pretty similar throttling deal as <a href="http://ajaxify.com/tutorial/">Ajaxagram</a>.</p>

<p><a href="http://tiddlywiki.mahemoff.com/SimpleMessagePlugin.html">Demo here</a>.</p>

<p>Latest version from <a href="http://trac.tiddlywiki.org/browser/Trunk/contributors/MichaelMahemoff/plugins/SimpleMessagePlugin?rev=10845">SimpleMessagePlugin</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/simplemessageplugin-unobtrusive-tiddlywiki-status-message/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JQuery IFrame Plugin</title>
		<link>http://softwareas.com/jquery-iframe-plugin</link>
		<comments>http://softwareas.com/jquery-iframe-plugin#comments</comments>
		<pubDate>Tue, 15 Sep 2009 23:10:52 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Scrumptious]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://softwareas.com/jquery-iframe-plugin</guid>
		<description><![CDATA[This article by Nick Zakas, covering some technical issues in iframe loading, triggered me to  surface a JQuery IFrame plugin I made a little while ago, which supports loading IFrames. (I did tweet it at the time, though I've since changed the location.)

JQuery IFrame plugin



The plugin basically tells you, the programmer of the parent [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/">This article by Nick Zakas</a>, covering some technical issues in iframe loading, triggered me to  surface a JQuery IFrame plugin I made a little while ago, which supports loading IFrames. (I did <a href="http://twitter.com/mahemoff/statuses/3177377341">tweet it</a> at the time, though I've since changed the location.)</p>

<p><a href="http://project.mahemoff.com/jquery-iframe/">JQuery IFrame plugin</a></p>

<p><a href="http://project.mahemoff.com/jquery-iframe/"><img style="width:400px;" src="http://img.skitch.com/20090915-k34qa5qjcxfht4axtrfdkcdni6.jpg"/></a></p>

<p>The plugin basically tells you, the programmer of the parent document, when your child iframe has loaded. It also has some other bells and whistles, like timing the load duration.</p>

<p>It's inspired by the use cases of WebWait (http://webwait.com) and the Scrumptious trails player (http://scrumptious.tv). Both are applications whose whole mission in life is to open up an external page in an iframe, and do something when it has loaded.</p>

<p>There's already an <a href="http://ideamill.synaptrixgroup.com/?p=6">IFrame JQuery plugin</a>, but it's to do with controlling what's inside the iframe, i.e. the situation which is only possible when the iframes are from the same domain. What I'm dealing with here is the parent knowing when the iframe is loaded, regardless of when it comes from and agnostic to what it does.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/jquery-iframe-plugin/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Modal Dialog JQuery Plugin</title>
		<link>http://softwareas.com/modal-dialog-jquery-plugin</link>
		<comments>http://softwareas.com/modal-dialog-jquery-plugin#comments</comments>
		<pubDate>Thu, 27 Aug 2009 16:03:46 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Lightbox]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://softwareas.com/modal-dialog-jquery-plugin</guid>
		<description><![CDATA[

This has been a while coming, but I made a little "yet another modal dialog lightbox JQuery plugin" thing this week.

Demo and Download for Modal Dialog - JQuery Plugin

It was driven by TiddlyDocs, but I've been wanting one anyway for a while. Mostly because lightbox libraries generally do some hocus-pocus on page load, like applying [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/mahemoff/status/1640629729"><img style="width:400px;" src="http://img.skitch.com/20090827-fd8efw4bp1bp8b85y84t93d9tf.jpg" /></a></p>

<p>This has been a while coming, but I made a little "yet another modal dialog lightbox JQuery plugin" thing this week.</p>

<p><a href="http://project.mahemoff.com/modal/">Demo and Download for Modal Dialog - JQuery Plugin</a></p>

<p>It was driven by <a href="http://tiddlydocs.com">TiddlyDocs</a>, but I've been wanting one anyway for a while. Mostly because lightbox libraries generally do some hocus-pocus on page load, like applying to everything marked rel="lightbox", but don't let you dynamically produce the lightbox yourself. That's fine for pages that are just a static image gallery, but not useful to someone building a dynamic web app.</p>

<p>I've subsequently used <a href="nyromodal.nyrodev.com/">nyromodal</a>, <a href="http://twitter.com/mahemoff/statuses/1647793685">on good advice</a>, but wanted something smalller and with a simple API for my main use case, which is just showing some text.</p>

<p>The plugin also simplifies work by not requiring you to install a separate CSS file. Doing that, and linking to it, as well as installing any images, is something that always slows me down when I want to start using a graphical client. In keeping with the "happy path" You-Aint-Gonna-Need-It (YAGNI) mantra, I'd rather keep a library to a single Javascript file - be evil and do styling in the library by default, but still support users who want to put custom CSS in a stylesheet.</p>

<p><img style="width:400px;" src="http://img.skitch.com/20090827-qqk7a963e6f3j758fntauu7nh2.jpg" /></p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/modal-dialog-jquery-plugin/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Towards A Single Page Application Framework</title>
		<link>http://softwareas.com/towards-a-single-page-application-framework</link>
		<comments>http://softwareas.com/towards-a-single-page-application-framework#comments</comments>
		<pubDate>Tue, 18 Aug 2009 02:02:57 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[SPA]]></category>
		<category><![CDATA[TiddlyWiki]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=590</guid>
		<description><![CDATA[Tonight, I was thinking of making a Twitter app to manage my various accounts (I have ~dormant accounts related to projects like @webwait and @listoftweets). The app would be holding username and password details for each of these accounts, so it made sense to build it as a Single Page Application (SPA). This way, a [...]]]></description>
			<content:encoded><![CDATA[<p>Tonight, I was thinking of making a Twitter app to manage my various accounts (I have ~dormant accounts related to projects like @webwait and @listoftweets). The app would be holding username and password details for each of these accounts, so it made sense to build it as a <a href="http://en.wikipedia.org/wiki/Single_page_application">Single Page Application</a> (SPA). This way, a more paranoid user could always keep the app in their local file system, while a less paranoid user could always stick the file on a protected server somewhere, having configured all the username-password details.</p>

<p>TiddlyWiki is a framework for developing SPAs. One might say it's <em>the</em> framework for developing SPAs, since there are no prominent alternatives. So my obvious choice was a TiddlyWiki. However, not too long ago, the TiddlyWiki core guys extracted out the secret sauce for SPAs: the ingenius bit of code that saves files without requiring any browser extensions. (I've tried to explain this to people and it always leaves even the most brilliant minds a little dumbstruck, but yes TiddlyWiki demonstrates there are pragmatic hacks that can be used to read a file into the browser and then write it out again.) I was keen to explore this saving mechanism, so experimentation ensued.</p>

<p>The file management techniques ship conveniently in a JQuery plugin, <strong>jQuery.twFile</strong>. There is a <a href="http://jquery.tiddlywiki.org/twFile.html">basic demo which lets you edit the entire text and save it</a>. The demo confused me at first - because it was editing the entire body of the file, I wasn't sure how to translate that info into what I, as an application developer needed. The demo is useful for framework developers understanding the plugin, but less so for application developers. So I extracted it into a demo that is still minimalistic, but closer to the kind of thing you'd do in an application.</p>

<p><a href="http://project.mahemoff.com/spa-demo.html">The SPA demo is here.</a></p>

<p><a href="http://project.mahemoff.com/spa-demo.html"><img style="width: 400px; border: 1px solid #999;"  src="http://img.skitch.com/20090818-xy1n926xgpfdbaua3x4typ4qfb.jpg" /></a></p>

<p>Once I did that, I realised what's required is a SPA framework. In practice, most developers using twFile will be keeping all the HTML, CSS, and Javascript in a single file, so it's possible to build a higher-level abstraction on twFile, so that developers can focus only on the content. I built the demo in a way that distinguished what was boilerplate framework code and what was application-specific HTML, CSS, and Javascript.</p>

<p>It was all still in one file, and that's fine for many developers - you can give the developer the file, tell them "edit these bits", and they can come up with something functional. I decided to extract things further though, and <a href="http://mini.softwareas.com/jinja-python-templating-lib-has-a-very-nice-w">found the Jinja templating framework to be useful here</a>. Jinja has a concept of template inheritance, so you can easily build up an "include" system.  The net effect is I was able to encapsulate SPA logic in a single file, which was passed through a Jinja processor to produce the executable HTML document.</p>

<p>The basic SPA logic is shown below:</p>

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

<div class="syntax_hilite"><span class="langName">HTML:</span><br /><div id="html-7">
<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;">{% extends &quot;spa-template.html&quot; %}</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">{% block title %}JQuery SPA demo{% endblock %}</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;">{% block css %}</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; etc etc</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; body { background: black; padding: 0; margin: 0; font-family: Gill Sans, sans-serif; }</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; h1 { background: white; color: black; padding: 10px 10px 0; margin: 0; height: 52px; }</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;">{% endblock %}</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">{% block html %}</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/h1.html"><span style="color: #000000; font-weight: bold;">&lt;h1&gt;</span></a></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/img.html"><span style="color: #000000; font-weight: bold;">&lt;img</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"logo"</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">"data:image/jpeg,%FFetc etc"</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/span.html"><span style="color: #000000; font-weight: bold;">&lt;span</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"title"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>JQuery-SPA Demo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/span&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;/h1&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;</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;">id</span>=<span style="color: #ff0000;">"main"</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;</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/ol.html"><span style="color: #000000; font-weight: bold;">&lt;ol&gt;</span></a></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: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span>Save this file to your local file system and open your local copy in the browser (using a file:/// URI). The browser might ask for special permission for this document, and you will need to grant it.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span>Type your message: <span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"message"</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">"change me"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/input&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span>Save this page: <span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"saveButton"</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">"Save"</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">"button"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&gt;</span></span></div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp;</div></li>
<li style="font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;color:#3A6A8B;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; <span style="color: #009900;"><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span>Hit shift-reload to perform a clean reload the page and observe that your message has been saved.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&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;"><span style="color: #000000; font-weight: bold;">&lt;/ol&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;</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/h3.html"><span style="color: #000000; font-weight: bold;">&lt;h3&gt;</span></a></span>What is this?<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/h3&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;</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/p.html"><span style="color: #000000; font-weight: bold;">&lt;p&gt;</span></a></span>This is a demo of an experimental Single Page Application I am building atop <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;">href</span>=<span style="color: #ff0000;">"http://jquery.tiddlywiki.org/twFile.html"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>jQuery.twFile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>, the file saving plugin extracted from TiddlyWiki. Forked from <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;">href</span>=<span style="color: #ff0000;">"http://jquery.tiddlywiki.org/twFileDemo.html"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>this twFile Demo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a&gt;</span></span>. Only tested on Firefox for now.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p&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;</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></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;">{% endblock %}</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">{% block javascript %}</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; $.spa.save = function(text) {</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; return text.replace(/<span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"message"</span>.*?<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;</span>\/input&gt;</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; &nbsp; &nbsp; &nbsp; '<span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"message"</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">"'+$("</span>#message<span style="color: #ff0000;">").val()+'"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/input&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; }</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;">{% endblock %} </div></li></ol></div>
</div></div>

<p><br /></p>

<p>So it contains separate HTML/CSS/Javascript blocks. Probably not a good engineering practice (though it doesn't impact on the end-user experience, which is always a single file), but it's convenient for now. The key SPA logic is here:</p>

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

<div class="syntax_hilite"><span class="langName">HTML:</span><br /><div id="html-8">
<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/li.html"><span style="color: #000000; font-weight: bold;">&lt;li&gt;</span></a></span>Type your message: <span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"message"</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">"change me"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/input&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/li&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; &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; $.spa.save = function(text) {</div></li>
<li style="font-weight: bold;color:#26536A;"><div style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">&nbsp; &nbsp; &nbsp; return text.replace(/<span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"message"</span>.*?<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;</span>\/input&gt;</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; &nbsp; &nbsp; &nbsp; '<span style="color: #009900;"><a href="http://december.com/html/4/element/input.html"><span style="color: #000000; font-weight: bold;">&lt;input</span></a> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">"message"</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">"'+$("</span>#message<span style="color: #ff0000;">").val()+'"</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/input&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; } </div></li></ol></div>
</div></div>

<p><br /></p>

<p>As an app developer, all you have to do is override $.spa.save (which in retrospect should be renamed as it doesn't actually perform the save). This function receives the text of the file as it was stored on disk when the page loaded. It must then return the text that should be saved to disk. Thus, it must store application state in HTML, probably by performing some kind of substitution.</p>

<p>Having put this together, I'm keen to proceed with the envisioned Twitter app. It's not yet clear if there's any mileage here over a regular TiddlyWiki, but as someone who is more familiar with starting apps from a blank HTML page (or a simple <a href="http://projectdeploy.com">Project Deploy*</a> template), it might end up being a more familiar way to kick an app off. Watch this space.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/towards-a-single-page-application-framework/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ColourLovers API &#8211; JSON Demos</title>
		<link>http://softwareas.com/colourlovers-api-json-demos</link>
		<comments>http://softwareas.com/colourlovers-api-json-demos#comments</comments>
		<pubDate>Sun, 02 Aug 2009 23:26:22 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[ColourLovers]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=563</guid>
		<description><![CDATA[About a year ago, I was excited to discover ColourLovers had an API. There is some great data about colours and palettes on that site, and some great possibilities for mashups - some as general-purpose art projects, and some as tools for designers.

However, I noticed there was no JSON-P interface, so there was no way [...]]]></description>
			<content:encoded><![CDATA[<p>About a year ago, I was excited to discover <a href="http://colourlovers.com">ColourLovers</a> had an API. There is some great data about colours and palettes on that site, and some great possibilities for mashups - some as general-purpose art projects, and some as tools for designers.</p>

<p>However, I noticed there was no <a href="http://ajaxian.com/archives/jsonp-json-with-padding">JSON-P</a> interface, so there was no way to write a pure browser-based mashup. I got in touch with them, and heard back from <a href="http://twitter.com/pureform">Chris Williams</a>, who to my pleasant surprise was willing to introduce JSON-P. And so we had some email discussion about the various options for the API interface (e.g. do you call it "jsonp" versus "callback"; do you use "real JSONP" versus just a callback function; do you hardcode the name of the callback function versus let the caller specify it as a parameter), and ultimately Chris went ahead and implemented it a short time later and published the API on January 26, 2009. Fantastic!</p>

<p>I offered to make some demos illustrating code usage, and did around that time, but never got around to publishing them until now. I've released the demos <a href="http://colourlovers.rainbowgelati.com">here</a>. There's a couple of JQuery demos, and one raw Javascript demo. I had fun making them and have plans to do a lot more with this API.</p>

<p><a href="http://colourlovers.rainbowgelati.com"><img src="http://img.skitch.com/20090802-p8jnmrj6u58421ebbbxrm9eige.jpg" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/colourlovers-api-json-demos/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>WebWait Two Point Oh</title>
		<link>http://softwareas.com/webwait-two-point-oh</link>
		<comments>http://softwareas.com/webwait-two-point-oh#comments</comments>
		<pubDate>Sat, 25 Jul 2009 00:39:15 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WebWait]]></category>

		<guid isPermaLink="false">http://softwareas.com/?p=560</guid>
		<description><![CDATA[I'm pleased to announce a major upgrade to WebWait, the first big upgrade since I launched the site 2.5 years ago. It's based on watching how people are using it, talking about it, and sending me direct feedback about it. Thanks to all who have provided feedback.



The new features are:


  Multiple sites You can [...]]]></description>
			<content:encoded><![CDATA[<p>I'm pleased to announce a major upgrade to <a href="http://webwait.com">WebWait</a>, the first big upgrade since I <a href="http://softwareas.com/time-your-website-with-webwaitcom">launched the site</a> 2.5 years ago. It's based on watching how people are using it, <a href="http://softwareas.com/webwait-in-the-wild ">talking about it</a>, and sending me direct feedback about it. Thanks to all who have provided feedback.</p>

<p><a href="http://img.skitch.com/20090725-85m6maa9b4geumcrtjb92i4m57.jpg"><img style="width: 400px;" src="http://img.skitch.com/20090725-85m6maa9b4geumcrtjb92i4m57.jpg" /></a></p>

<p>The new features are:</p>

<ul>
  <li><strong>Multiple sites</strong> You can keep typing in new URLs and hitting "Add". This will put them in a queue of sites to eventually be benchmarked. (I decided against a big textarea where you could type in all URLs at once; this would be confusing to the majority of WebWait users, who are casual visitors wanting to check out the time for their own site.)</li>
  <li><strong>Stats</strong> Average, median, and standard deviation for each website, in a summary table. Indeed, the summary table is the cultural centre for all these new features - when you queue up a site, it's immediately added to the table.</li>
  <li><strong>Export</strong> The export feature seems to be popular in <a href="http://listoftweets.com">List Of Tweets</a>. I took the same UI concept and applied it here, so you can export data in plain text, HTML, and CSV format. The CSV is especially interesting as one of the people who've given me feedback is a statistician who's planning to run analysis on some data.</li>
  <li><strong>Call Data</strong> View times for each individual call.</li>
  <li><strong>Expand/Collapse Call Data</strong> You can choose whether to show call data or not. Collapsing call data gives you a neat overview of stats for each domain.</li>
  <li><strong>Delete</strong> You can delete individual call data, or delete an entire website record. This is useful for outlier data; for example, you can see how fast the site loads from your browser cache, by turning browser cache on and deleting just the first call in the sequence.</li>
  <li><strong>Stats</strong> Average, median, and standard deviation for each website.</li>
  <li><strong>Browser compatibility.</strong> WebWait didn't work upon launch in Safari, but it does now work in recent versions of Safari (I think a change in 3.0 made it work again <img src='http://softwareas.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ), and works fine in Chrome too. This is important for users testing how their website loads in different browsers.</li>
</ul>

<p>Thanks for reading. As always, let us know what you think of the site and anything else you'd like to see.</p>

<p>Table with expanded results:</p>

<p><img src="http://img.skitch.com/20090725-871fne1hgd8m3ek7ui2rcgn2xj.jpg" style="width:400px;" /></p>

<p>Table with collapsed results:</p>

<p><img src="http://img.skitch.com/20090725-c7mhdcpg3gctmu9a8p9ji4yk9y.jpg" style="width:400px;" /></p>

<p>Export results data (text):</p>

<p><img src="http://img.skitch.com/20090725-dty5ik9incfaw66c71fwppg1g2.jpg" style="width:400px;" /></p>

<p>Export results data (HTML):</p>

<p><img src="http://img.skitch.com/20090725-q61r6iwcwahpeeke97efjts7hh.jpg" style="width:400px;" 
/></p>

<p>Export results data (CSV):</p>

<p><img src="http://img.skitch.com/20090725-q53xx18mf2b42bq3a39371gbqi.jpg" style="width:400px;" /></p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/webwait-two-point-oh/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>TiddlyWeb-JQuery Comments Plugin</title>
		<link>http://softwareas.com/tiddlyweb-jquery-comments-plugin</link>
		<comments>http://softwareas.com/tiddlyweb-jquery-comments-plugin#comments</comments>
		<pubDate>Tue, 21 Jul 2009 15:39:59 +0000</pubDate>
		<dc:creator>mahemoff</dc:creator>
				<category><![CDATA[SoftwareDev]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[Osmosoft]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[tiddlyweb]]></category>

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

TiddlyWeb-JQuery Comments Plugin - Screencast @ Vimeo

I've extracted from Scrumptious a nested comments plugin you can integrate into any POJA (plain ol' Javascript app). You can find it here in the repo: TiddlyWeb-JQuery Comments Plugin.

As the README explains, usage is a one-liner once you've set it up. Just do $(selector).comments("topic"). The topic is an identifier [...]]]></description>
			<content:encoded><![CDATA[<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5694409&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=5694409&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object></p>

<p><a href="http://vimeo.com/5694409">TiddlyWeb-JQuery Comments Plugin - Screencast @ Vimeo</a></p>

<p>I've extracted from <a href="http://scrumptious.tv">Scrumptious</a> a nested comments plugin you can integrate into any POJA (plain ol' Javascript app). You can find it here in the repo: <a href="http://trac.tiddlywiki.org/browser/Trunk/contributors/MichaelMahemoff/lib/comments">TiddlyWeb-JQuery Comments Plugin</a>.</p>

<p>As the <a href="http://trac.tiddlywiki.org/browser/Trunk/contributors/MichaelMahemoff/lib/comments/README">README</a> explains, usage is a one-liner once you've set it up. Just do $(selector).comments("topic"). The topic is an identifier for the set of comments; so that when the UI loads, it pulls down all comments with that ID in its "topic" field. Internally, topic acts as the root of the comments tree...but you don't really need to know that.</p>

<p>This plugin is a JQuery equivalent of <a href="http://tiddlywiki.mahemoff.com/CommentsPlugin.html">the TiddlyWiki comments plugin</a>, minus some of the more exotic options, and the ability to delete. Eventually, I hope to introduce those things, but only as the need arises - so if you're using this, please let me know how I can improve it.</p>
]]></content:encoded>
			<wfw:commentRss>http://softwareas.com/tiddlyweb-jquery-comments-plugin/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
