<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>Semicolon</title>
	
	<link>http://thunderguy.com/semicolon</link>
	<description>Software, the Internet and you.</description>
	<lastBuildDate>Fri, 10 Feb 2012 03:53:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/semicolon" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="semicolon" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>A spoonful of Git helps the Subversion go down</title>
		<link>http://thunderguy.com/semicolon/2012/01/25/a-spoonful-of-git-helps-the-subversion-go-down/</link>
		<comments>http://thunderguy.com/semicolon/2012/01/25/a-spoonful-of-git-helps-the-subversion-go-down/#comments</comments>
		<pubDate>Wed, 25 Jan 2012 00:50:18 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Git]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://www.thunderguy.com/semicolon/?p=506</guid>
		<description><![CDATA[Here&#8217;s how I use Git to work on projects that use Subversion for version control. The basic idea is to use the Git master branch to track the Subversion trunk. All my coding happens on Git branches. That way I can use Git to easily work on multiple different features or bugfixes at once, with [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s how I use Git to work on projects that use Subversion for version control. The basic idea is to use the Git master branch to track the Subversion trunk. All my coding happens on Git branches. That way I can use Git to easily work on multiple different features or bugfixes at once, with all the usual git benefits of disconnected operation, speed and flexibility. Then I commit to SVN when my work is ready.<span id="more-506"></span></p>
<p>So the basic workflow is to work in Git branches. To make sure the Git master and the Subversion trunk are in sync, I follow two basic rules. First, the only ways the Git master changes are:</p>
<ul>
<li>an update from SVN trunk</li>
<li>a merge from another Git branch</li>
</ul>
<p>Second, the only time I ever use SVN to commit or update is when I am on a clean Git master.</p>
<p>Here are the detailed steps I use.</p>
<p><strong>Starting off</strong></p>
<p><code>&gt; git checkout master<br />
&gt; svn update<br />
<em>Updated to revision 435</em><br />
&gt; git commit -a<br />
&gt; git tag svn-435</code></p>
<p>Now master is up to date with the SVN trunk.</p>
<p><strong>Working on code</strong></p>
<p><code>&gt; git checkout -B niftyFeature</code></p>
<p>Create a branch to work on a feature. This overwrites any existing niftyFeature branch.</p>
<p><em>(hack)</em><br />
<code>&gt; git commit .</code><br />
<em>(hack)</em><br />
<code>&gt; git commit .</code><br />
<em>(hack)</em><br />
<code>&gt; git commit .</code></p>
<p><strong>Getting ready to commit to SVN</strong></p>
<p><code>&gt; git checkout master<br />
&gt; svn update<br />
<em>Updated to revision 439</em></code></p>
<p>There will be no conflicts since Git&#8217;s master branch just tracks the SVN trunk.</p>
<p><code>&gt; git add --all<br />
&gt; git commit -m"Update to SVN revision 439"<br />
&gt; git tag svn-439</code></p>
<p>The tag can be useful for diffing later on.</p>
<p>Now comes the scary part.</p>
<p><code>&gt; git rebase master niftyFeature</code></p>
<p>That rebase essentially merges your work into the latest from the SVN trunk. Git rebase seems to work better than svn merge, but even so, you might have to resolve conflicts in the normal Git way.</p>
<p>The rebase also switches to the niftyFeature branch.</p>
<p><em>(test)</em></p>
<p>If there are problems:</p>
<p><em>(hack)</em><br />
<code>&gt; git commit .</code></p>
<p><strong>Committing to SVN</strong></p>
<p><code>&gt; git checkout master<br />
&gt; git merge niftyFeature</code></p>
<p>This is a no-fail fast-forward merge thanks to the previous rebase.</p>
<p><code>&gt; svn commit<br />
<em>Committed revision 440</em></code></p>
<p>The SVN commit may update SVN keywords if you&#8217;re using them. To avoid confusing Git, commit these changes too:</p>
<p><code>&gt; git commit -a -m"Update SVN keywords"<br />
&gt; git tag svn-440</code></p>
<p>I suppose this workflow is nothing but an <a href="http://en.wikipedia.org/wiki/Greenspun's_tenth_rule">ad hoc, informally-specified, bug-ridden, slow implementation of half</a> of <a href="http://schacon.github.com/git/git-svn.html">git-svn</a>. I already know Subversion and am learning Git, and my goal was to practise my Git rather than learn a third set of commands (git-svn). I plan to use SVN a lot less in the future, so this way I will only have to forget one set of commands, not two.</p>
<p><strong>Bonus tip: Backups</strong></p>
<p>You can clone your repository to another location on your file system. A good choice might be your Dropbox folder or similar. This makes it trivial to keep your entire repository backed up.</p>
<p><code>&gt; git clone --bare . /dropbox/projectName.git<br />
&gt; git remote add backup /dropbox/projectName.git<br />
&gt; git push backup</code></p>
<p>Making it a bare repository avoids problems with pushing. Then whenever you feel like backing up (i.e. all the time), just do this again:</p>
<p><code>&gt; git push backup</code></p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/LooyFbPDa1s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2012/01/25/a-spoonful-of-git-helps-the-subversion-go-down/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML5 — Barcamp Auckland 5</title>
		<link>http://thunderguy.com/semicolon/2011/07/22/html5-barcamp-auckland-5/</link>
		<comments>http://thunderguy.com/semicolon/2011/07/22/html5-barcamp-auckland-5/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 20:28:31 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[#!]]></category>
		<category><![CDATA[Barcamp]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://thunderguy.com/semicolon/?p=626</guid>
		<description><![CDATA[The last proper session I went to at Barcamp Auckland 5 was &#8220;Extreme AJAX &#8211; beyond the hashbang, building a robust single page JS framework and URL schema&#8221;, presented by Barry Hannah (@barryhannah) &#038; Mark Zeman (@markzeman). They worked on the excellent newzealand.com redesign and gave some insight into its engineering. At a high level, [...]]]></description>
			<content:encoded><![CDATA[<p>The last proper session I went to at <a href="http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/">Barcamp Auckland 5</a> was &#8220;Extreme AJAX &#8211; beyond the hashbang, building a robust single page JS framework and URL schema&#8221;, presented by Barry Hannah (<a href="http://twitter.com/#!/barryhannah">@barryhannah</a>) &#038; Mark Zeman (<a href="http://twitter.com/#!/markzeman">@markzeman</a>). They worked on the excellent <a href="http://www.newzealand.com/">newzealand.com</a> redesign and gave some insight into its engineering.<span id="more-626"></span></p>
<p>At a high level, the most interesting part of the design is the navigation: no hierarchy, just tags. Opinions were divided, but I like the purity and elegance of the idea, and the implementation gives a lot of structure to the tags.</p>
<p>At a low level, they described the initial URL scheme they came up with. The site is implemented as a single-page site, with all content updates done with Ajax. For modern browsers, they use the <a href="http://www.w3.org/TR/html5/history.html">history API</a> to seamlessly change the URLs. For example, if a user clicks a &#8220;Travel&#8221; link, the browser address bar will switch from <tt>http://nz.com/</tt> to <tt>http://nz.com/travel</tt> without refreshing the whole page. (Opera offer a good <a href="http://dev.opera.com/articles/view/introducing-the-html5-history-api/">history API introduction</a>.)</p>
<p>Browsers that don&#8217;t support the history API instead use Google&#8217;s <a href="http://code.google.com/web/ajaxcrawling/docs/specification.html">Hash fragments specification</a>: browsers would see the URL <tt>http://nz.com/#!travel</tt>, while web crawlers would see <tt>http://nz.com/?_escaped_fragment_=travel</tt> . (See the spec for the reasoning behind this.)</p>
<p>Eventually they realised they didn&#8217;t need to use hashbangs at all. HTML5 browsers, with their fancy history API, end up being able to use plain URLs like <tt>http://nz.com/travel</tt> without ever refreshing the whole page. But crawlers can use the same URLs to fetch whole pages &#8212; the backend can easily tell whether a request is coming from a crawler or a browser. And less capable browsers can just use a plain hashy URL like <tt>http://nz.com/#travel</tt>.</p>
<p>This is quite a nice solution, except that if a web crawler does get hold of an URL like <tt>http://nz.com/#travel</tt>, it will only ever see the site homepage. That&#8217;s an SEO fail. But they point out that this probably won&#8217;t have much of an impact because the proportion of such links floating around won&#8217;t be high.</p>
<p>They talked about various libraries they used to do this: jQuery plugins <a href="https://github.com/defunkt/jquery-pjax">Pjax</a> and <a href="http://plugins.jquery.com/project/history-js">History.js</a> and the JavaScript MVC framework <a href="http://documentcloud.github.com/backbone/">Backbone</a>. (Poking around the Pjax page I discovered a very useful online <a href="http://closure-compiler.appspot.com/">Closure compiler service</a> that actually hosts compiled code!)</p>
<p>I really enjoyed seeing this lively presentation from a team who are pushing a large public website into the HTML5 world. I&#8217;m feeling inspired for my next project!</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/UwqggbFPdAc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/07/22/html5-barcamp-auckland-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Development productivity — Barcamp Auckland 5</title>
		<link>http://thunderguy.com/semicolon/2011/07/22/development-productivity-barcamp-auckland-5/</link>
		<comments>http://thunderguy.com/semicolon/2011/07/22/development-productivity-barcamp-auckland-5/#comments</comments>
		<pubDate>Thu, 21 Jul 2011 12:34:19 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Barcamp]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Git]]></category>

		<guid isPermaLink="false">http://thunderguy.com/semicolon/?p=617</guid>
		<description><![CDATA[Last weekend&#8217;s Barcamp Auckland unconference had social issues, comedy and politics, but of course no Barcamp would be complete without a heapin&#8217; helping of software development geekery. Mal Curtis (@snikchnz) gave a packed presentation on Web Development Productivity, subtitled &#8220;What I use to quickly develop, deploy and maintain html, css, js, php &#038; ruby code [...]]]></description>
			<content:encoded><![CDATA[<p>Last weekend&#8217;s <a href="http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/">Barcamp Auckland</a> unconference had social issues, comedy and politics, but of course no Barcamp would be complete without a heapin&#8217; helping of software development geekery. Mal Curtis (<a href="http://twitter.com/#!/snikchnz">@snikchnz</a>) gave a packed presentation on Web Development Productivity, subtitled &#8220;What I use to quickly develop, deploy and maintain html, css, js, php &#038; ruby code at learnable.com and (a lil&#8217; bit) sitepoint.com. Git, Sass, Testing (Rspec, Cucumber, PHP too), Continuous Integration and deployment.&#8221; Actually that pretty much covers it.<span id="more-617"></span></p>
<p>But there were some particular highlights for me. Git, of course; everybody loves Git. In fact, 5 years ago I started a project in my day job. I strongly advocated using Subversion, and though there was some resistance (&#8220;What&#8217;s wrong with CVS?&#8221;) we did go with SVN. Now all our projects use Subversion. And now, working on an updated project for the same client, I&#8217;m keen to move to Git and it looks as if we&#8217;ll be doing that. Maybe 5 years from now we&#8217;ll be moving on to the next big version control paradigm. Nah, that&#8217;ll never happen, because Git is already version control Nirvana. Mmm, this Kool-Aid is delicious.</p>
<p>Mal recommended <a href="http://code.google.com/p/macvim/">MacVim</a>. I have installed it now. I spend a lot of time using Vim on various OSes, and I only know about 5 commands. Maybe if I switch to MacVim I will actually become a proper Vim user instead of a perpetual newbie.</p>
<p>He also spoke very highly of <a href="http://sass-lang.com/">Sass</a>, an &#8220;extension of CSS3, adding nested rules, variables, mixins, selector inheritance, and more&#8221;.I&#8217;ve always been intrigued by Sass and <a href="http://lesscss.org/">Less</a> and their ilk, but I worry that it&#8217;ll be too easy to write logical and clear Sass code that expands to CSS code with complicated selectors, leading to cascade problems, debugging nightmares and general unhappiness. (Coincidentally, a few days later Stephen Tudor pointed out a few of these issues in <a href="http://stephentudor.com/blog/2011/07/09/responsible-sass-authoring/">Responsible Sass Authoring</a>.) But Mal pointed out that you don&#8217;t have to go all-in: just a few key features (like mixins and variables) will make a big difference.</p>
<p>I&#8217;m convinced it&#8217;s worth a try.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/TdmKQMv02Yo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/07/22/development-productivity-barcamp-auckland-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Society — Barcamp Auckland 5</title>
		<link>http://thunderguy.com/semicolon/2011/07/17/society-barcamp-auckland-5/</link>
		<comments>http://thunderguy.com/semicolon/2011/07/17/society-barcamp-auckland-5/#comments</comments>
		<pubDate>Sun, 17 Jul 2011 09:24:13 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Barcamp]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[society]]></category>

		<guid isPermaLink="false">http://thunderguy.com/semicolon/?p=609</guid>
		<description><![CDATA[I attended a few sessions at Barcamp Auckland yesterday that concerned the Internet&#8217;s role in society. Vikram Kumar (@vikram_nz) and (@robertobrien) hosted a discussion about designing privacy into services and products. This was a wide-ranging talk &#8212; I learned about a few interesting projects. Fire Eagle, from Yahoo!, is a framework for building location-awareness into [...]]]></description>
			<content:encoded><![CDATA[<p>I attended a few sessions at <a href="http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/">Barcamp Auckland</a> yesterday that concerned the Internet&#8217;s role in society. Vikram Kumar (<a href="http://twitter.com/#!/vikram_nz">@vikram_nz</a>) and  (<a href="http://twitter.com/#!/robertobrien">@robertobrien</a>) hosted a discussion about designing privacy into services and products. This was a wide-ranging talk &#8212; I learned about a few interesting projects.<span id="more-609"></span></p>
<p><a href="http://fireeagle.yahoo.net/">Fire Eagle</a>, from Yahoo!, is a framework for building location-awareness into an application in a way that offers users fine-grained control over the privacy of their location information.</p>
<p>Ideo&#8217;s free <a href="http://www.ideo.com/work/human-centered-design-toolkit/">Human-Centered Design Toolkit</a> is intended to help international staff and volunteers &#8220;understand a community’s needs in new ways, find innovative solutions to meet those needs, and deliver solutions with financial sustainability in mind.&#8221; It&#8217;s designed specifically for social enterprises operating in impoverished communities in Africa, Asia, and Latin America, but I&#8217;m sure there&#8217;s a lot in it for social enterprises in general. And it&#8217;s free, which is nice.</p>
<p>Vikram and Robert also handed round a copy of <a href="http://www.businessmodelgeneration.com/book">Business Model Generation</a> (&#8220;A handbook for visionaries, game changers and challengers.&#8221;), a rather nice coffee-table book about building and maintaining modern business models. It looked well worth reading as far as I could tell. There&#8217;s an iPad app too.</p>
<p>Later, Peter Mangin (<a href="http://twitter.com/#!/peteinakl">@peteinakl</a>) facilitated a nicely nuanced discussion on the evolution of social networks. He pointed out that they&#8217;re not evil &#8212; not even Facebook! &#8212; they&#8217;re just businesses trying to make money. He singled out two Google initiatives as being forces for good in the space. Obviously, the Circles feature in <a href="https://plus.google.com/">Google+</a> aims to clarify the privacy ambiguities that Facebook has struggled with (and it may well eat Facebook and Twitter&#8217;s lunches in the process.) Meanwhile, their <a href="http://www.dataliberation.org/">Data Liberation Front</a> aims to give Google&#8217;s users as much control as possible over their data. As people become more concerned about privacy, this will become a Google feature that Facebook will simply <em>have</em> to copy.</p>
<p>This year, for the first time Barcamp hosted a panel discussion. There were three members of parliament, representing the three main parties, and four others representing various organisations and views. The discussion was worthwhile, though with the Barcamp crowd the views expressed were pretty much what you&#8217;d expect: <em>More Power to the Internet!</em> Of the politicians, Clare Curran the Labour MP and Gareth Hughes the Green MP both seemed to have a good grip on the issues. National MP Sam Lotu-Liga mostly just parroted the party line. At least he was obviously not pandering to the partisan audience.</p>
<p>It was great to see a lot of discussion on wider social issues relating to technology at the Barcamp, rather than just coding and designing the latest web app. There was a bit of that though: I&#8217;ll write up my notes for that sometime soon.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/FzITfJcjePQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/07/17/society-barcamp-auckland-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Pomodoro Technique — Barcamp Auckland 5</title>
		<link>http://thunderguy.com/semicolon/2011/07/17/the-pomodoro-technique-barcamp-auckland-5/</link>
		<comments>http://thunderguy.com/semicolon/2011/07/17/the-pomodoro-technique-barcamp-auckland-5/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 11:13:25 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Barcamp]]></category>
		<category><![CDATA[Pomodoro]]></category>
		<category><![CDATA[productivity]]></category>

		<guid isPermaLink="false">http://thunderguy.com/semicolon/?p=592</guid>
		<description><![CDATA[The Pomodoro Technique is a way of managing your time for improved productivity. At Barcamp Auckland 5 today, Carol Green (@carolgreen) and Noemi Selisker (@thenoemi) gave a useful outline of the process, from a beginner&#8217;s point of view &#8212; Noemi has been using the technique for a couple of weeks, and Carol is just about [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://thunderguy.com/semicolon/wp/wp-content/uploads/2011/07/pomodoro-logo.png" alt="" title="Pomodoro Technique logo" width="150" height="150" class="alignleft size-full wp-image-604" />The <a href="http://www.pomodorotechnique.com/">Pomodoro Technique</a> is a way of managing your time for improved productivity. At <a href="http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/">Barcamp Auckland 5</a> today, Carol Green (<a href="http://twitter.com/#!/carolgreen">@carolgreen</a>) and Noemi Selisker (<a href="http://twitter.com/#!/thenoemi">@thenoemi</a>) gave a useful outline of the process, from a beginner&#8217;s point of view &#8212; Noemi has been using the technique for a couple of weeks, and Carol is just about to start.<span id="more-592"></span></p>
<p>I was already aware of the basic technique: work in uninterrupted 25-minute bursts, followed by a 5-minute break. This 30-minute cycle is called a Pomodoro. If a Pomodoro is interrupted, you have to start the timer again. After four Pomodoros, have a longer break of 15-30 minutes.</p>
<p>Carol and Noemi fleshed out these rules with descriptions of how you should plan your day&#8217;s work beforehand, and evaluate it at the end. This is important for efficiency, but also for motivation &#8212; it&#8217;s easier to stick with the technique if you can see the progress you&#8217;re making. The final rule is to remember that &#8220;The Next Pomodoro Will Go Better&#8221;.</p>
<p>I have downloaded the <a href="http://www.pomodorotechnique.com/products.html">Pomodoro Technique Book</a> and will try the technique for myself in the coming weeks.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/JDLWeJFPIhE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/07/17/the-pomodoro-technique-barcamp-auckland-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Barcamp Auckland 5</title>
		<link>http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/</link>
		<comments>http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/#comments</comments>
		<pubDate>Sat, 16 Jul 2011 11:07:37 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Barcamp]]></category>

		<guid isPermaLink="false">http://thunderguy.com/semicolon/?p=599</guid>
		<description><![CDATA[About 300 of New Zealand&#8217;s brightest gathered in Auckland today for the Barcamp Auckland 5 unconference. As with BCA4 last year, it was all pretty well-organised for an unconference, though there was an unsettling lack of espresso coffee. There was good variety in the various sessions I attended. One was on 1Password, a cross-platform password [...]]]></description>
			<content:encoded><![CDATA[<p>About 300 of New Zealand&#8217;s brightest gathered in Auckland today for the <a href="http://bca.geek.nz/">Barcamp Auckland 5</a> unconference. As with <a href="http://www.thunderguy.com/semicolon/2010/07/19/barcamp-auckland-4/">BCA4</a> last year, it was all pretty well-organised for an unconference, though there was an unsettling lack of espresso coffee.<span id="more-599"></span></p>
<p><img src="http://thunderguy.com/semicolon/wp/wp-content/uploads/2011/07/IMG_7880-300x293.jpg" alt="" title="BCA5 nametag" width="300" height="293" class="alignnone size-medium wp-image-601" /></p>
<p>There was good variety in the various sessions I attended. One was on <a href="http://agilebits.com/products/1Password">1Password</a>, a cross-platform password and information management tool. It looked useful, but quite heavyweight &#8212; there&#8217;s no easy way to use it on a computer unless you can run or install the 1Password program on it. Still, maybe a good solution to the problems of juggling dozens of website usernames and passwords.</p>
<p>I also attended a live recording of <a href="http://www.discourse.co.nz/">The Discourse Weekly Show</a>. Ben &#038; Morgan were pretty amusing, but the rough and ready setup and the general lack of microphone technique in the audience might not translate that well to the recorded result. <a href="http://www.discourse.co.nz/2011/07/episode-2-09bca-barcamp-special-live-show/">Listen to the show</a> if you don&#8217;t believe me.</p>
<p>Other sessions I attended roughly covered the areas of productivity, society and development. I&#8217;ll write up my notes on them in the next few days.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/bD3yMPg2sVw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/07/17/barcamp-auckland-5/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Search Fixer: a WordPress plugin</title>
		<link>http://thunderguy.com/semicolon/2011/06/08/search-fixer-wordpress-plugin/</link>
		<comments>http://thunderguy.com/semicolon/2011/06/08/search-fixer-wordpress-plugin/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 09:45:21 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.thunderguy.com/semicolon/?p=578</guid>
		<description><![CDATA[I have created a plugin to solve a subtle but annoying WordPress bug. With the Search Fixer plugin installed, search links like those in Search Meter&#8216;s &#8220;Recent Searches&#8221; widget should work correctly. The bug is WordPress bug 13961. This prevents &#8220;pretty&#8221; search URLs from working properly. For example, http://example.com/search/hello%20world should search the example.com blog for [...]]]></description>
			<content:encoded><![CDATA[<p>I have created a plugin to solve a subtle but annoying WordPress bug. With the Search Fixer plugin installed, search links like those in <a href="http://www.thunderguy.com/semicolon/wordpress/search-meter-wordpress-plugin/">Search Meter</a>&#8216;s &#8220;Recent Searches&#8221; widget should work correctly.<span id="more-578"></span></p>
<p>The bug is <a href="http://core.trac.wordpress.org/ticket/13961">WordPress bug 13961</a>. This prevents &#8220;pretty&#8221; search URLs from working properly. For example, <em>http://example.com/search/hello%20world</em> should search the example.com blog for the words &#8220;hello&#8221; and &#8220;world&#8221;, but because of the bug it actually searches for &#8220;hello%20world&#8221; and fails to find anything.</p>
<p>Search Fixer should make everything work as you&#8217;d expect. Sometime during <del datetime="2012-02-02T22:06:46+00:00">2011</del> 2012 the bug fix should make it into the WordPress core. At that time I will update this page and we will all be able to deactivate Search Fixer and breathe a sigh of relief.</p>
<h3>Install</h3>
<p>The <a href="http://wordpress.org/extend/plugins/search-fixer/">Search Fixer</a> plugin is in the WordPress plugin repository, so you can install it using the Plugins section in your WordPress console.</p>
<p>Feel free to <a href="https://github.com/bennettmcelwee/Search-Fixer">fork the project on GitHub</a> if you want to tinker with it. And <a href="http://www.thunderguy.com/semicolon/donate/">send me a Bitcoin</a> if you find the plugin useful.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/sDP0c3J0azQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/06/08/search-fixer-wordpress-plugin/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Simple Combo jQuery plugin 1.1</title>
		<link>http://thunderguy.com/semicolon/2011/06/07/simple-combo-jquery-plugin-1-1/</link>
		<comments>http://thunderguy.com/semicolon/2011/06/07/simple-combo-jquery-plugin-1-1/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 02:06:59 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thunderguy.com/semicolon/?p=558</guid>
		<description><![CDATA[I have just updated my Simple Combo jQuery plugin to work with recent versions of jQuery. When jQuery 1.5 came out, there was a change to its selector engine that stopped Simple Combo from modifying select lists. Then jQuery 1.5.2 introduced a subtle change to the events code that interfered with typing into combos. Both [...]]]></description>
			<content:encoded><![CDATA[<p>I have just updated my <a href="http://plugins.jquery.com/project/simpleCombo">Simple Combo jQuery plugin</a> to work with recent versions of jQuery. When jQuery 1.5 came out, there was a change to its selector engine that stopped Simple Combo from modifying select lists. Then jQuery 1.5.2 introduced a subtle change to the events code that interfered with typing into combos.</p>
<p>Both these issues have now been fixed. <span id="more-558"></span>I also added a couple of new tweaks:</p>
<ul>
<li>The typed-in option now has a value attribute so its value can be submitted by a form. (Suggested by <a href="http://www.thunderguy.com/semicolon/2009/07/16/simple-combo-box-jquery-plugin/comment-page-2/#comment-128571">Trent Richardson</a>)</li>
<li>The automatically added classname is now &#8220;simpleComboActive&#8221;, which should reduce accidental name collisions. (Suggested by <a href="http://www.thunderguy.com/semicolon/2009/07/16/simple-combo-box-jquery-plugin/comment-page-1/#comment-99320">Jonathan Greene</a>)</li>
</ul>
<p>I have also updated the <a href="http://www.thunderguy.com/semicolon/resources/simpleCombo-demo.html">demo page</a> to use jQuery 1.6.1, just to prove that Simple Combo is moving with the times.</p>
<p>The source code is now on <a href="https://github.com/bennettmcelwee/Simple-Combo">GitHub</a> so, as they say, fork away.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/D2qN3s_q9bc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/06/07/simple-combo-jquery-plugin-1-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple Twitter widget</title>
		<link>http://thunderguy.com/semicolon/2011/05/25/a-simple-twitter-widget/</link>
		<comments>http://thunderguy.com/semicolon/2011/05/25/a-simple-twitter-widget/#comments</comments>
		<pubDate>Wed, 25 May 2011 00:14:52 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.thunderguy.com/semicolon/?p=533</guid>
		<description><![CDATA[This blog&#8217;s sidebar displays my latest Twitter update. I did this manually instead of using a plugin because I couldn&#8217;t find a lightweight plugin that did what I want, and I thought it would be a quick and simple project. So here&#8217;s how I did it. My Twitter widget is written purely in HTML and [...]]]></description>
			<content:encoded><![CDATA[<p>This blog&#8217;s sidebar displays my latest Twitter update. I did this manually instead of using a plugin because I couldn&#8217;t find a lightweight plugin that did what I want, and I thought it would be a quick and simple project. So here&#8217;s how I did it.<span id="more-533"></span></p>
<p>My Twitter widget is written purely in HTML and JavaScript. This means that I can simply put the code into a WordPress Text widget. I don&#8217;t have to edit my theme or write a plugin.</p>
<p>Initially I got the code for the widget straight from the Twitter website. There was a section where you could copy a little bit of HTML to paste into your site (or in a Text widget). This was great because the code was structured to be easily modifiable. They&#8217;ve changed to a more opaque implementation now, but they still serve the old scripts from their site. I&#8217;ve used these, plus an undocumented feature of the Twitter API, to make my own little Twitter widget.</p>
<p>Here&#8217;s the code, with interesting bits highlighted:</p>
<pre style="overflow-x:scroll"><code>&lt;div id="twitter_div"&gt;
&lt;ul id="twitter_update_list"&gt;&lt;/ul&gt;
&lt;div&gt;<strong style="color:red">&lt;a href="http://www.twitter.com/bnnt"&gt;&lt;img alt="Follow bnnt on Twitter" src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png"&gt;&lt;/a&gt;</strong>&lt;/div&gt;
&lt;/div&gt;
<strong style="color:red">&lt;script type="text/javascript" src="http://twitter.com/javascripts/blogger.js"&gt;&lt;/script&gt;</strong>
&lt;script type="text/javascript"&gt;
function twitterCallback2_filtered(timeline) {
	// Try to select a non-reply
	var select = 0, i;
	for (i = 0; i &amp;lt; timeline.length; ++i) {
		if (timeline[i].text.charAt(0) != '@') {
			select = i;
			break;
		}
	}
	var status = timeline[select];
	// Edit the status
	status.text = status.text.replace(/ #(?:yam|fb|in)\b/g, '');
	twitterCallback2([status]);
}
&lt;/script&gt;
<strong style="color:red">&lt;script type="text/javascript" src="http://api.twitter.com/1/statuses/user_timeline.json?screen_name=bnnt&amp;amp;count=5&amp;amp;include_rts=true&amp;amp;callback=twitterCallback2_filtered"&gt;&lt;/script&gt;</strong></code></pre>
<p>Here&#8217;s a breakdown of the code.</p>
<p>The &#8220;Follow me on Twitter&#8221; button is taken straight from <a href="http://twitter.com/about/resources/buttons">Twitter&#8217;s Follow Buttons page</a>.</p>
<pre><code>&lt;a href="http://www.twitter.com/bnnt"&gt;
&lt;img alt="Follow bnnt on Twitter"
src="http://twitter-badges.s3.amazonaws.com/follow_me-b.png"&gt;
&lt;/a&gt;</code></pre>
<p>Then the little formatting script Twitter have thoughtfully provided. It contains a function called <code>twitterCallback2</code>, which formats an array of tweets and writes them into a div with ID <code>twitter_update_list</code>.</p>
<pre><code>&lt;script type="text/javascript"
src="http://twitter.com/javascripts/blogger.js"&gt;
&lt;/script&gt;</code></pre>
<p>Twitter no longer seem to link to this script from their site, but it&#8217;s still there if you know where to look. I suppose thousands of sites will break if they ever remove this. It&#8217;s pretty simple &#8211; at some point I will write my own even simpler one and ditch theirs.</p>
<p>At first I simply used the above script for my Twitter widget. But then I wanted to make a couple of changes. So I wrote a little filter which would tweak the returned tweets and then pass the result to the <code>twitterCallback2</code> function.</p>
<pre><code>function twitterCallback2_filtered(timeline) {</code></pre>
<p>First, I wanted to avoid displaying @replies, since they usually make no sense without context. For example: <a href="http://twitter.com/#!/bnnt/status/58740693497159680">@DavidPlumpton &#8220;They also serve who only stand and look out of the window&#8221; (apologies to Milton)</a>. (Actually, that doesn&#8217;t make much sense even <em>with</em> the context.)</p>
<p>To do this, I set the API call to fetch the last 5 tweets instead of the last one. Then I search through until I find one that isn&#8217;t an @reply. If they&#8217;re all @replies then I just give up and take the first one.</p>
<pre><code>	// Try to select a non-reply
	var select = 0, i;
	for (i = 0; i &amp;lt; timeline.length; ++i) {
		if (timeline[i].text.charAt(0) != '@') {
			select = i;
			break;
		}
	}
	var status = timeline[select];</code></pre>
<p>I also wanted to filter out &#8220;control&#8221; hashtags that have nothing to do with the tweet. For example, the hashtag <code>#in</code> in a tweet will cross-post the tweet to my LinkedIn account. I don&#8217;t need this to show up in the widget. Likewise for <code>#fb</code> (Facebook) and <code>#yam</code> (Yammer).</p>
<pre><code>	// Edit the status
	status.text = status.text.replace(/ #(?:yam|fb|in)\b/g, '');
	twitterCallback2([status]);
}</code></pre>
<p>The last line of the function calls <code>twitterCallback2</code> to render the tweet.</p>
<p>The last piece of the puzzle is the Twitter REST API call that actually fetches the tweets. I call <a href="http://dev.twitter.com/doc/get/statuses/user_timeline">user_timeline</a> with the undocumented <code>callback</code> parameter to turn the response into <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> and call my <code>twitterCallback2_filtered</code> function. (To use the raw JSON result I would have to contend with the same-origin policy, which would complicate things considerably.)</p>
<pre><code>&lt;script type="text/javascript"
src="http://api.twitter.com/1/statuses/user_timeline.json?
screen_name=bnnt&amp;amp;count=5&amp;amp;include_rts=true&amp;
amp;callback=twitterCallback2_filtered"&gt;&lt;/script&gt;</code></pre>
<p>As I mentioned, the final step is to paste the code into a Text widget in my WordPress Admin screens. If you want to use this too, just change the two occurrences of &#8220;bnnt&#8221; to your own Twitter handle (unless you want to display my tweets on your blog).</p>
<p><iframe allowtransparency="true" frameborder="0" scrolling="no" src="http://platform.twitter.com/widgets/follow_button.html?screen_name=bnnt&#038;show_count=false" style="width:300px; height:20px;"></iframe></p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/z0mKmc9xYXc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/05/25/a-simple-twitter-widget/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>jQuery 1.5: Better, Faster… Bigger</title>
		<link>http://thunderguy.com/semicolon/2011/02/17/jquery-1-5-better-faster-bigger/</link>
		<comments>http://thunderguy.com/semicolon/2011/02/17/jquery-1-5-better-faster-bigger/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 23:06:44 +0000</pubDate>
		<dc:creator>Bennett</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.thunderguy.com/semicolon/?p=503</guid>
		<description><![CDATA[Back when jQuery was heading towards its 1.0 release, one of the things that really impressed me was its small size. Only about 15KB of uncompressed code was enough to turn JavaScript (and particularly DOM manipulation) from a chore into a pleasure. But with each new release, new features and speed optimisations have inevitably bloated [...]]]></description>
			<content:encoded><![CDATA[<p>Back when <a href="http://jquery.com/">jQuery</a> was heading towards its 1.0 release, one of the things that really impressed me was its small size. Only about 15KB of uncompressed code was enough to turn JavaScript (and particularly DOM manipulation) from a chore into a pleasure. But with each new release, new features and speed optimisations have inevitably bloated the library. Every time a new release came out, it seemed to me that the svelte jQuery I knew and loved was receding further into the past. Now that jQuery 1.5 is out, I thought I would see how jQuery has grown in size as well as stature with each release.</p>
<p><img class="alignnone size-full wp-image-502" title="Graph of jQuery download size over time" src="http://www.thunderguy.com/semicolon/wp/wp-content/uploads/2011/02/jquery-size.png" alt="Graph of jQuery download size over time" width="594" height="390" /><br />
<span id="more-503"></span></p>
<p>The graph just about says it all. It shows the size of a zipped jQuery download for each release (I omitted a few of the minor releases due to laziness). I have overlaid a linear trendline, which fits pretty well and shows that jQuery&#8217;s size has grown about 4.6KB every year. jQuery 1.5 is three times the download size of jQuery 1.0. The uncompressed JavaScript is closer to <em>five</em> times as big, as the table shows.</p>
<p><!-- Styles in the body are invalid, but I'm not sure how better to do this. --></p>
<style type="text/css">
/* width */
td, th {
	text-align: right;
	margin: 0;
	padding: 0.1em;
}
th:first-child,
td:first-child {
	padding-left: 0.5em;
}
th:last-child,
td:last-child {
	padding-right: 0.5em;
}
tr:nth-child(odd) {
	background-color: #eee;
}
colgroup.number {
	width: 4em;
}
th.version {
	padding-left: 1em;
}
th:nth-child(n+5),
td:nth-child(n+5) {
	color: gray;
	font-size: 80%;
}
tr.major {
	font-weight: bold;
}
</style>
<table cellpadding="0" cellspacing="0">
<colgroup span="2" />
<colgroup span="5" class="number" />
<tr>
<th>Date</th>
<th class="version">Version</th>
<th>Zip</th>
<th>Size</th>
<th>Pack</th>
<th>Minify</th>
<th>Pack.Zip</th>
<th>Min.Zip</th>
</tr>
<tr class="major">
<td>4/02/2006</td>
<td>0.x</td>
<td>6</td>
<td>19</td>
<td>13</td>
<td></td>
<td>6</td>
<td></td>
</tr>
<tr class="major">
<td>26/08/2006</td>
<td>1.0</td>
<td>9</td>
<td>45</td>
<td>17</td>
<td></td>
<td>9</td>
<td></td>
</tr>
<tr class="major">
<td>14/01/2007</td>
<td>1.1</td>
<td>11</td>
<td>56</td>
<td>21</td>
<td></td>
<td>11</td>
<td></td>
</tr>
<tr class="major">
<td>10/09/2007</td>
<td>1.2</td>
<td>15</td>
<td>78</td>
<td>27</td>
<td>45</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16/09/2007</td>
<td>1.2.1</td>
<td>15</td>
<td>79</td>
<td>27</td>
<td>46</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>14/01/2008</td>
<td>1.2.2</td>
<td>16</td>
<td>94</td>
<td>29</td>
<td>52</td>
<td>15</td>
<td>16</td>
</tr>
<tr>
<td>7/02/2008</td>
<td>1.2.3</td>
<td>16</td>
<td>95</td>
<td>30</td>
<td>53</td>
<td>15</td>
<td>16</td>
</tr>
<tr>
<td>19/05/2008</td>
<td>1.2.4</td>
<td>16</td>
<td>96</td>
<td>30</td>
<td>54</td>
<td>15</td>
<td>16</td>
</tr>
<tr>
<td>20/05/2008</td>
<td>1.2.5</td>
<td>17</td>
<td>98</td>
<td>31</td>
<td>55</td>
<td>16</td>
<td>17</td>
</tr>
<tr>
<td>24/05/2008</td>
<td>1.2.6</td>
<td>17</td>
<td>98</td>
<td>31</td>
<td>55</td>
<td>16</td>
<td>17</td>
</tr>
<tr class="major">
<td>14/01/2009</td>
<td>1.3</td>
<td>19</td>
<td>115</td>
<td></td>
<td>54</td>
<td></td>
<td>19</td>
</tr>
<tr>
<td>21/01/2009</td>
<td>1.3.1</td>
<td>19</td>
<td>115</td>
<td></td>
<td>54</td>
<td></td>
<td>19</td>
</tr>
<tr>
<td>20/02/2009</td>
<td>1.3.2</td>
<td>20</td>
<td>118</td>
<td></td>
<td>56</td>
<td></td>
<td>20</td>
</tr>
<tr class="major">
<td>14/01/2010</td>
<td>1.4</td>
<td>24</td>
<td>155</td>
<td></td>
<td>69</td>
<td></td>
<td>24</td>
</tr>
<tr>
<td>25/01/2010</td>
<td>1.4.1</td>
<td>24</td>
<td>157</td>
<td></td>
<td>70</td>
<td></td>
<td>24</td>
</tr>
<tr>
<td>19/02/2010</td>
<td>1.4.2</td>
<td>24</td>
<td>161</td>
<td></td>
<td>71</td>
<td></td>
<td>24</td>
</tr>
<tr>
<td>16/10/2010</td>
<td>1.4.3</td>
<td>27</td>
<td>177</td>
<td></td>
<td>76</td>
<td></td>
<td>27</td>
</tr>
<tr>
<td>11/11/2010</td>
<td>1.4.4</td>
<td>27</td>
<td>179</td>
<td></td>
<td>77</td>
<td></td>
<td>27</td>
</tr>
<tr class="major">
<td>31/01/2011</td>
<td>1.5</td>
<td>29</td>
<td>208</td>
<td></td>
<td>83</td>
<td></td>
<td>29</td>
</tr>
</table>
<p>The numbers in the first row may be slightly speculative, since I had to reconstruct some of those files &#8212; I didn&#8217;t just have them lying around.</p>
<p>In the old days, the jQuery website used to talk about the size of the library in uncompressed form or in packed form. At some point they changed this and started quoting the minified and gzipped size. This confused me at first &#8212; I thought that jQuery had actually gotten <em>smaller</em> &#8212; but then I realised it was just a bit of spin.</p>
<p>The jQuery team used to use <a href="http://dean.edwards.name/packer/">Packer</a> (or some variant of it) to squash the JavaScript before gzipping, but from version 1.2 they started using Minify too and from 1.3 they switched to Minify exclusively. jQuery 1.5 is minified using what looks like a custom script driven by <a href="http://nodejs.org/">Node.js</a>. It&#8217;s interesting to see that minify performs quite poorly compared to Packer, but the resulting file gzips much better. The end result is still pretty lean &#8212; 29KB for the best JavaScript library around &#8212; but it&#8217;s a long way from the 6KB download I first played with five years ago.</p>
<img src="http://feeds.feedburner.com/~r/semicolon/~4/0EhLl7lyqBc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://thunderguy.com/semicolon/2011/02/17/jquery-1-5-better-faster-bigger/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

