<?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/"
	>

<channel>
	<title>Jaysen Marais &#187; web development</title>
	<atom:link href="http://www.jaysenmarais.com/blog/category/web-development/feed" rel="self" type="application/rss+xml" />
	<link>http://www.jaysenmarais.com/blog</link>
	<description>Making it happen, bit by bit</description>
	<lastBuildDate>Sat, 10 Apr 2010 10:19:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Deploy a rails app to bluehost without SSH</title>
		<link>http://www.jaysenmarais.com/blog/20100410/deploy_a_rails_app_to_bluehost_without_ssh</link>
		<comments>http://www.jaysenmarais.com/blog/20100410/deploy_a_rails_app_to_bluehost_without_ssh#comments</comments>
		<pubDate>Sat, 10 Apr 2010 10:19:33 +0000</pubDate>
		<dc:creator>jaysen</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[bluehost]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[RoR]]></category>
		<category><![CDATA[shared hosting]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[troubleshooting]]></category>

		<guid isPermaLink="false">http://www.jaysenmarais.com/blog/?p=227</guid>
		<description><![CDATA[code { font-size: 12px; font-family: Bitstream Vera Sans Mono, Monaco, monospace; } .snippet { text-align: left; font-size: 12px; display: block; border: solid 1px #eee; background: #f8f8f8; padding: 10px; font-family: Bitstream Vera Sans Mono, Monaco, monospace; margin-bottom: 1em; } .snippet .comment { font-style: italic; color: #AAA; } .snippet .keyword { font-weight: bold; } .snippet .string { [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
	code { font-size: 12px; font-family: Bitstream Vera Sans Mono, Monaco, monospace; }
	.snippet { text-align: left; font-size: 12px; display: block; border: solid 1px #eee; background: #f8f8f8; padding: 10px; font-family: Bitstream Vera Sans Mono, Monaco, monospace; margin-bottom: 1em; }
   		.snippet .comment { font-style: italic; color: #AAA; }
		.snippet .keyword { font-weight: bold; }
		.snippet .string { color: #0031ff; }
		.snippet .entity { text-decoration: underline; }
		.snippet .storage { color: #888; }
		.snippet .support { color: #006803; }
		.snippet .constant, .variable { color: #F0F; }
</style>
<p><img src="http://www.jaysenmarais.com/blog_media/201004/rails_on_bluehost.png" width="230" height="121" alt="rails on bluehost" style="float: right; margin-left: 15px;" /></p>
<p>I&#8217;ve been doing a little free-lance web development again lately. It&#8217;s been a while and the landscape&#8217;s changed in the 2 or 3 years since I was last freelancing. Specifically the &#8216;minimum requirements&#8217; for a public facing site and the quality of the &#8216;cheap&#8217; generic hosts have both increased (for the better). In light of these two factors I&#8217;ve been having a go at making some basic &#8216;web-presence&#8217; sites using <a href="http://rubyonrails.org/">ruby on rails</a>.</p>
<p>Learning enough rails to make a simple site was easy enough, but the deployment turned out to be a bit of a puzzle. Particularly as <a href="http://bluehost.com/">bluehost</a>, whose control panel is otherwise excellent, just doesn&#8217;t seem to have its rails story sorted. To make matters worse, every <a href="http://www.google.com/search?q=rails+bluehost">&#8220;rails bluehost&#8221;</a> tutorial out there starts with &#8220;you need SSH access&#8221; and bluehost now requires a <a href="http://helpdesk.bluehost.com/index.php/kb/article/180">faxed or emailed copy of the account-holder&#8217;s drivers license</a> to grant SSH access. Seeing as my clients are generally the hosting account holders, this wasn&#8217;t an option for me.</p>
<p>After a bit of trial and error I&#8217;ve discovered that you can indeed deploy a basic Ruby on Rails site to bluehost without SSH access (assuming you have ftp access). Here&#8217;s how:
</p>
<ol>
<li>
<p><strong style="display:block;">Create rails directory.</strong>Use your ftp client to create a directory alongside the <code>{app}</code> directory to which the domain/sub-domain points.I&#8217;ve called mine <code>{app}_rails</code>, but it can be called anything.</p>
</li>
<li>
<p><strong style="display:block;">Upload rails app.</strong>Upload your rails app into the newly created <code>{app}_rails</code> directory.</p>
</li>
<li>
<p><strong style="display:block;">Symlink to rails public directory using temporary PHP.</strong>We need to <a href="http://en.wikipedia.org/wiki/Symbolic_link">symlink</a> the <code>{app}</code> directory (to which the domain/sub-domain points) to the <code>{app}_rails/public</code> directory. Ordinarily we&#8217;d use the trusty <a href="http://en.wikipedia.org/wiki/Ln_%28Unix%29#Symbolic_link_creation_and_deletion">ln -s</a> command, but we can also do it without SSH access by using <a href="http://php.net/manual/en/function.symlink.php">PHP&#8217;s symlink function</a>.</p>
<p>Create a php script on your local machine (I&#8217;ve called mine <code>symlink.php</code>) with the following contents (replacing the <code>{account}</code> and <code>{app}</code> tokens with your own). Make sure the <code>{app}</code> directory doesn&#8217;t already exist (rename/move/delete it if it does).</p>
<p><code class="snippet"><span class="text"><span class="source"><span class="punctuation">&lt;?php</span> <span class="support">symlink</span>(<span class="string"><span class="punctuation">'</span><span class="meta">/home/atfraser/public_html/maketimelapse_rails/public</span><span class="punctuation">'</span></span>, <span class="string"><span class="punctuation">'</span><span class="meta">/home/atfraser/public_html/maketimelapse</span><span class="punctuation">'</span></span>)<span class="punctuation">;</span> <span class="punctuation"><span class="source">?</span>&gt;</span></span></span></code>
<p>Upload the <code>symlink.php</code> to an accessable directory and then browse to it in your browser. If the script succeeds you&#8217;ll be greeted with a blank page (otherwise you&#8217;ll get errors). Once run successfully, you can delete the symlink php script (it&#8217;s no longer needed).</p>
</li>
<li>
<p><strong style="display:block;">Ensure <code>dispatch.fcgi</code> exists.</strong>To run under apache, a rails app needs fcgi dispatchers. My understanding is that <a href="http://guides.rubyonrails.org/2_3_release_notes.html#other-railties-changes">rails 2.3 no longer fcgi dispatchers by default</a> so if you didn&#8217;t use the <code>--with-dispatches</code> option when you created your app (I didn&#8217;t) you&#8217;ll need to create them on your local machine using the following command:</p>
<p><code class="snippet">rake rails:update:generate_dispatchers</code>
<p>Then upload the created <code>dispatch.fcgi</code>, <code>dispatch.cgi</code> and <code>dispatch.rb</code> files from your local<code>public</code> directory to <code>{app}_rails/public</code> directory on bluehost.</p>
</li>
<li>
<p><strong style="display:block;">Enable <code>dispatch.fcgi</code> in <code>.htaccess</code>.</strong>Create a <code>.htaccess</code> file inside your <code>{app}_rails/public</code> directory with the following contents:</p>
<div class="snippet"><span class="support">AddHandler</span> fcgid-script .fcgi<br/><span class="support">AddHandler</span> cgi-script .cgi<br/><br/><span class="support">RewriteEngine</span> On<br/><br/><span class="support">RewriteBase</span> /<br/><span class="support">RewriteRule</span> <span class="string">^$</span> <span class="string">index.html</span> <span class="string">[QSA]</span><br/><span class="support">RewriteRule</span> <span class="string">^([^.]+)$</span> <span class="string">$1.html</span> <span class="string">[QSA]</span><br/><span class="support">RewriteCond</span> <span class="support"><span class="punctuation">%{</span>REQUEST_FILENAME}</span> <span class="string">!-f</span><br/><span class="support">RewriteRule</span> <span class="string">^(.*)$</span> <span class="string">dispatch.fcgi</span> <span class="string">[QSA,L]</span><br/><br/><span class="support">ErrorDocument</span> 500 <span class="string"><span class="punctuation">&#8220;</span>&lt;h2&gt;Application error&lt;/h2&gt;Rails application failed to start properly<span class="punctuation">&#8220;</span></span></div>
</li>
<li>
<p><strong style="display:block;">Check permissions using FTP client.</strong>We need to check/set some permissions. Again, we can&#8217;t use the standard <code><a href="http://en.wikipedia.org/wiki/Chmod">chmod</a></code> command without SSH access but luckily most modern ftp clients can also view/set permissions (select the file/directory then &#8984;-i in <a href="http://www.panic.com/TRANSMIT/">Transmit</a> or &#8216;right-click &gt; File permissions&#8217; in <a href="http://filezilla-project.org/">FileZilla</a>). Set the appopriate permissions for the following files/directories (list courtesy <a href="http://6brand.com/application-error-rails-app-failed-to-start-properly.html">Jack Danger Canty)</a>: </p>
<table border="0" cellspacing="3" cellpadding="0">
<thead>
<tr>
<th scope="col">File/Directory</th>
<th scope="col">Permission</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding-right:10px;"><code>{app}_rails/public<code></td>
<td>755</td>
</tr>
<tr>
<td style="padding-right:10px;"><code>{app}_rails/public/.htaccess<code></td>
<td>755</td>
</tr>
<tr>
<td style="padding-right:10px;"><code>{app}_rails/public/dispatch.fcgi<code></td>
<td>755</td>
</tr>
<tr>
<td style="padding-right:10px;"><code>{app}_rails/public/dispatch.cgi<code></td>
<td>755</td>
</tr>
<tr>
<td style="padding-right:10px;"><code>{app}_rails/log<code></td>
<td>775</td>
</tr>
<tr>
<td style="padding-right:10px;"><code>{app}_rails/tmp<code></td>
<td>775</td>
</tr>
</tbody>
</table>
</li>
<li>
<p><strong style="display:block;">Handling rails gems version issues.</strong>If you're app still isn't working, check the error logs in cpanel. It may be that the version of the rails version you built against isn't available on the shared host. In this case,you'll need to either freeze the gems into your app locally (then upload the <code>vendor/gems</code> directory) or comment out the following line in <code>environment.rb</code> which refers to their specific version (risky).</p>
<p><code class="snippet">rake rails:freeze:gems</code></li>
</ol>
<p>That should be it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jaysenmarais.com/blog/20100410/deploy_a_rails_app_to_bluehost_without_ssh/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Synchronize bookmarks with Delicious &amp; Firefox</title>
		<link>http://www.jaysenmarais.com/blog/20090502/delicious</link>
		<comments>http://www.jaysenmarais.com/blog/20090502/delicious#comments</comments>
		<pubDate>Sat, 02 May 2009 22:35:40 +0000</pubDate>
		<dc:creator>jaysen</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[bookmarks]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[synchronizing]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://jaysenmarais.com/blog/?p=223</guid>
		<description><![CDATA[The web is awesome, but managing URLs is a pain. That pain is magnified if you use multiple machines and made worse if you use multiple operating systems (not to mention home vs. work, desktop vs. phone etc). There are roughly a million ways to handle this problem. Here&#8217;s mine. Step 1. Move bookmarks to [...]]]></description>
			<content:encoded><![CDATA[<p>The web is awesome, but managing URLs is a pain. That pain is magnified if you use multiple machines and made worse if you use multiple operating systems (not to mention home vs. work, desktop vs. phone etc). There are roughly a million ways to handle this problem. Here&#8217;s mine.</p>
<p><center><img src="/blog_media/200905/cloud_diagram.png" width="450" height="270" alt="synchronizing bookamrks between multiple computers and OSes using delicious" /></center></p>
<h4>Step 1. Move bookmarks to delicious.com</h4>
<p>About 2 years ago I moved all my bookmarks to <a href="http://www.delicious.com">delicious.com</a>, a &#8216;social bookmarking&#8217; service which stores your bookmarks and enables you to access, share and organize (via tagging) these bookmarks over the web. Over time it&#8217;s become second nature to save anything interesting I find to my delicious account.</p>
<p><center><img src="/blog_media/200905/delicious_screen.png" width="486" height="184" alt="delicious.com screenshot" /></center></p>
<h4>Step 2. Install delicious.com browser extension</h4>
<p>Whilst delicious (and its ilk) can be used via the web interface, things really get interesting when you install the relevant browser extensions. These give you an experience much like regular browser-based bookmarking, but with synchronization and superior bookmark search.</p>
<ul>
<li>Official <a href="https://addons.mozilla.org/en-US/firefox/addon/3615">Delicious Bookmarks</a> extension for firefox</a> (any OS). Best.</li>
<li>Official <a href="http://delicious.com/help/quicktour/ie">Delicious Bookmarks</a> Add-on for Internet Explorer (windows)</li>
<li>Unofficial <a href="http://delicioussafari.com/">DeliciousSafari</a> plugin for Safari (mac)</li>
<li>Unofficial <a href="http://delicioussafari.com/bookmarks.php">Bookmarks</a> app for iPhone</li>
</ul>
<h4>Step 3. Specify &#8220;everyday&#8221; bookmarks</h4>
<p><img src="/blog_media/200905/manage_favourite_tags.png" width="180" height="108" alt="specifying favourite tags" style="float:right;margin-left:15px;margin-bottom:5px;" />We all have bookmarks we use everyday. Delicious allows me to group mine together by applying a common tag (I use the tag &#8220;me&#8221;). I then tell the <a href="https://addons.mozilla.org/en-US/firefox/addon/3615">Delicious Bookmarks</a> extension for firefox that the &#8220;me&#8221; tag denotes my favourites and viola! All my everyday bookmarks appear in Firefox&#8217;s toolbar. Better still, any additions or edits I make to this list of favourite bookmarks are propagated across all my browsers and computers.</p>
<h4>Step 4. Bring on the favicons!</h4>
<p>Although the Delicious extension for Firefox is great, it pays too much head to Firefox conventions for my liking. Specifically it doesn&#8217;t display <a href="http://en.wikipedia.org/wiki/Favicon">favicons</a> on mac (firefox doesn&#8217;t do toolbar favicons on mac by default) and doesn&#8217;t offer the ability to hide toolbar labels (which take up space). Luckily Firefox is highly customizable so I&#8217;ve managed to put together a simple Firefox extension which overrides these design decisions (and fix an intermittent &#8220;huge favicon&#8221; issue on mac Firefox). Behold: my <a href="http://jaysenmarais.com/blog/bits/delicious-bookmarks-toolbar/">Delicious Bookmarks Toolbar extension</a>.</p>
<p><center><a href="http://jaysenmarais.com/blog/bits/delicious-bookmarks-toolbar/"><img src="/blog_media/200905/extension_preview.png" width="481" height="279" alt="the 'Delicious Bookmarks Toolbar' extension replaces the Delicious Bookmark labels with favicons (mac &amp; pc)" style="border:none;" /></a></center></p>
<p>By the way, if you thought this blog post was written simply as an excuse to link to that simple extension, you&#8217;d be right.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jaysenmarais.com/blog/20090502/delicious/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ragged CSS: makes life easier</title>
		<link>http://www.jaysenmarais.com/blog/20090126/ragged-css-makes-life-easier</link>
		<comments>http://www.jaysenmarais.com/blog/20090126/ragged-css-makes-life-easier#comments</comments>
		<pubDate>Mon, 26 Jan 2009 19:55:44 +0000</pubDate>
		<dc:creator>jaysen</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[code formatting]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[semantic html]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[web design]]></category>

		<guid isPermaLink="false">http://jaysenmarais.com/blog/?p=95</guid>
		<description><![CDATA[The web community is generally coming (or has come) to accept that &#8216;semantic&#8217; class naming conventions (&#8216;old school&#8217; elements with classes describing content not appearance) are preferable to the 'boldGreyLink' type conventions popular around the millennium. Millenium era HTML &#38; CSS &#8216;Semantic&#8217; era HTML &#38; CSS &#60;html&#62; &#60;head&#62; &#60;title&#62;'Millenium' era&#60;/title&#62; &#60;style type="text/css"&#62; div.redSubHead { color: [...]]]></description>
			<content:encoded><![CDATA[<p>The web community is generally coming (or has come) to accept that &#8216;semantic&#8217; class naming conventions (&#8216;old school&#8217; elements with classes describing content not appearance) are preferable to the <code>'boldGreyLink'</code> type conventions popular around the millennium.	</p>
<table cellpadding="0" cellspacing="10" border="0">
<tr>
<th style="padding:5px;">Millenium era HTML &amp; CSS</th>
<th style="padding:5px;">&#8216;Semantic&#8217; era HTML &amp; CSS</th>
</tr>
<tr>
<td style="position:relative; width:50%;padding:5px;" valign="top">
<pre style="border:solid 1px #eee;padding:10px; background:#f8f8f8;line-height:1.2em;">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;'Millenium' era&lt;/title&gt;
&lt;style type="text/css"&gt;
<span style="color:#c00;">div.redSubHead</span> {
  color: red;
}
<span style="color:#c00;">p.greyText</span> {
  color: #666;
}
<span style="color:#c00;">td.columnHeaderCell</span> {
  font-weight: bold;
}
<span style="color:#c00;">td.oddRowCell</span> {
  background: #eee;
}
<span style="color:#c00;">td.evenRowCell</span> {
  background: #ddd;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

  <span style="color:#c00;">&lt;div class="redSub"&gt;</span>sub 1&lt;<span style="color:#c00;">/div&gt;</span>
  <span style="color:#c00;">&lt;p class="greyText"&gt;</span>blah&lt;<span style="color:#c00;">/p&gt;</span>
  &lt;table&gt;

    &lt;tr&gt;
      <span style="color:#c00;">&lt;td class="colHeader"&gt;</span>A<span style="color:#c00;">&lt;/td&gt;</span>
      <span style="color:#c00;">&lt;td class="colHeader"&gt;</span>B<span style="color:#c00;">&lt;/td&gt;</span>
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td <span style="color:#c00;">class="oddRow"</span>&gt;1&lt;/td&gt;
      &lt;td <span style="color:#c00;">class="oddRow"</span>&gt;2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td <span style="color:#c00;">class="evenRow"</span>&gt;3&lt;/td&gt;
      &lt;td <span style="color:#c00;">class="evenRow"</span>&gt;4&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
</td>
<td valign="top" style="width:50%;padding:5px;">
<pre style="border:solid 1px #eee;padding:10px; background:#f8f8f8;line-height:1.2em;">&lt;html&gt;
&lt;head&gt;
&lt;title&gt;'Semantic' era&lt;/title&gt;
&lt;style type="text/css"&gt;
<span style="color:#0a0;">.section h2</span> {
  color: red;
}
<span style="color:#0a0;">.section p</span> {
  color: #666;
}
<span style="color:#0a0;">.section thead th</span> {
  font-weight: bold;
}
<span style="color:#0a0;">.section td</span> {
  background: #ddd;
}
<span style="color:#0a0;">.section tr.odd td</span>  {
  background: #eee;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  <span style="color:#0a0;">&lt;div class="section"&gt;</span>
    <span style="color:#0a0;">&lt;h2&gt;</span>sub 1&lt;<span style="color:#0a0;">/h2&gt;</span>
    <span style="color:#0a0;">&lt;p&gt;</span>blah&lt;<span style="color:#0a0;">/p&gt;</span>
    &lt;table&gt;
      <span style="color:#0c0;">&lt;thead&gt;</span>
        &lt;tr&gt;
          <span style="color:#0a0;">&lt;th&gt;</span>A<span style="color:#0a0;">&lt;/th&gt;</span>
          <span style="color:#0a0;">&lt;th&gt;</span>B<span style="color:#0a0;">&lt;/th&gt;</span>
        &lt;/tr&gt;
      <span style="color:#0a0;">&lt;/thead&gt;</span>
      &lt;tr <span style="color:#0a0;">class="odd"</span>&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;3&lt;/td&gt;
        &lt;td&gt;4&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/table&gt;
  <span style="color:#0a0;">&lt;/div&gt;</span>
&lt;/body&gt;
&lt;/html&gt;</pre>
</td>
</tr>
<tr>
<td valign="top" style="padding:5px;">
<ol style="color:#900;">
<li>document structure inferred</li>
<li>classes describe appearance (volatile)</li>
<li>direct class application bloats html</li>
<li>changing style properties causes headaches (change all instance names or they&#8217;ll be out of sync with appearance).
			</ol>
</td>
<td valign="top" style="padding:5px;">
<ol style="color:#090;">
<li>document structure inherent</li>
<li>classes describe content (stable)</li>
<li>&#8216;container&#8217; classes give context to descendants</li>
<li>appearance (volatile) is abstracted from structure (stable). Redesign is anticipated &amp; therefore easier</li>
</ol>
</td>
</tr>
</table>
<p>One pillar of the &#8216;semantic&#8217; technique is the sparing application of <code>class</code> attributes, primarily to container elements. Elements are &#8216;caught&#8217; using CSS <a href="http://www.w3.org/TR/CSS2/selector.html#descendant-selectors">&#8216;descendant&#8217; selectors</a> (multi-part) which target hierarchies rather than using simple <a href="http://www.w3.org/TR/CSS2/selector.html#class-html">class selectors</a> which require a directly applied <code>class</code> attribute. Using descendant selectors respects the hierarchical nature of the <abbr title="Document Object Model">DOM</abbr> but makes writing bulk CSS quite tricky. Why? Mainly because CSS stylesheets (and style blocks) are fundamentally rule <b>lists</b>, but the DOM elements which our descendent selectors target are obviously <b>trees</b>. How do we bridge the gap between these fundamentally different structures?</p>
<h4>Enter &#8216;ragged&#8217; CSS</h4>
<p>In 2006 I (then a contracting developer) found myself filling the shoes of a fantastic design contractor whose contract was up but sadly not extended (project managers eternally underfund and misunderstand UI). I was the new &#8216;CSS guy&#8217; for a project with scores of developers, hundreds of pages and crippling compatibility/accessibility requirements. I wasn&#8217;t really qualified for the task, but my predecessor gave me a CSS tip that got me through: &#8220;don&#8217;t sweat the properties, focus on rule hierarchies&#8221;.</p>
<p>This rule-centric approach is most clearly evident in the CSS formatting style I picked up on that project and used ever since; a style I call &#8216;<b>Ragged CSS</b>&#8216;.</p>
<table cellpadding="0" cellspacing="10" border="0">
<tr>
<th style="padding:5px;">&#8216;tall&#8217; CSS</th>
<th style="padding:5px;">&#8216;ragged&#8217; CSS</th>
</tr>
<tr>
<td valign="top" style="padding:5px;">
<pre style="border:solid 1px #eee;padding:10px; background:#f8f8f8;line-height:1.2em;">
.section h2 {
  color: red;
}
.section p {
  color: #666;
}
.section thead th {
  font-weight: bold;
}
.section td {
  background: #ddd;
}
.section tr.odd td  {
  background: #eee;
}</pre>
</td>
<td valign="top" style="padding:5px;">
<pre style="border:solid 1px #eee;padding:10px; background:#f8f8f8;line-height:1.2em;">
.section { }
  .section h2 { color: red; }
  .section p { color: #666; }
  .section table { }
    .section thead th { font-weight: bold; }
    .section td { background: #ddd; }
      .section tr.odd td { background: #eee; }</pre>
</td>
</tr>
</table>
<p>It differs from the common &#8216;tall&#8217; CSS formatting style in only a few (primarily cosmetic) ways:</p>
<ol>
<li><b style="display:block;">One line per rule, one rule per line</b>There may be hundreds of rules, but each will only have a handful of properties.
	</li>
<li>
		<b style="display:block;">Indent CSS rules to represent target element hierarchy</b>A block of markup (e.g. a calendar) will typically involve several rules (perhaps dozens). Indenting rules more clearly indicates how their properties will cascade.</p>
<li>
		<b style="display:block;">Make rules for &#8216;landmark&#8217; elements (empty rules if necessary)</b>Adding an empty rule for element&#8217;s whose classes are used in subsequent selectors makes indentation hierarchy far clearer (improves readability).
	</li>
<li>
		<b style="display:block;">&#8216;namespace&#8217; your rules to avoid conflict</b>Class names may be repeated on large projects unintentionally. Target &#8216;abc&#8217; class elements inside &#8216;xyz&#8217; class elements using a &#8216;.xyz .abc&#8217; selector rather than a global &#8216;.abc&#8217; selector to avoid tainting someone else&#8217;s unrelated &#8216;abc&#8217; class.
	</li>
<li>
		<b style="display:block;">Avoid element prefixes sparingly in your selectors</b>Don&#8217;t use a <code>'span.content'</code> selector where a plain <code>'.content'</code> selector will do. Dogmatic prefixing (i.e. increasing <a href="http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/">specificity</a> unnecessarily) makes your rules unnecessarily vulnerable to otherwise inconsequential markup changes (changing the <code>span</code> to a <code>div</code> for instance).
	</li>
</ol>
<p>I&#8217;ve been using this formatting style for a few years now and it&#8217;s made complex CSS development a snap (browser quirks aside). If you&#8217;re writing &#8216;tall&#8217; CSS (or using a tool which generates it), give ragged CSS a go on your next project. Your future self (and/or your successor) will thank you for it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jaysenmarais.com/blog/20090126/ragged-css-makes-life-easier/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pico redux</title>
		<link>http://www.jaysenmarais.com/blog/20070730/pico-redux</link>
		<comments>http://www.jaysenmarais.com/blog/20070730/pico-redux#comments</comments>
		<pubDate>Mon, 30 Jul 2007 07:31:05 +0000</pubDate>
		<dc:creator>jaysen</dc:creator>
				<category><![CDATA[web development]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[hku]]></category>
		<category><![CDATA[hong kong]]></category>
		<category><![CDATA[pico]]></category>
		<category><![CDATA[uni]]></category>

		<guid isPermaLink="false">http://jaysenmarais.com/blog/20070730/pico-redux/</guid>
		<description><![CDATA[Recently, I created an IM icon for a friend. It&#8217;s a fairly straight-forward appropriation&#160;of the classic Che&#160;Guevara icon, which&#160;normally I&#8217;d avoid but the Simon&#8217;s surname is pronounced &#8216;Che&#8217;, so my hands were tied. an IM icon created for a friend (whose name is a homonym for che&#8217;s) In the process I decided to&#160;adorn my IM [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I created an IM icon for a friend. It&#8217;s a fairly straight-forward appropriation&nbsp;of the classic Che&nbsp;Guevara icon, which&nbsp;normally I&#8217;d avoid but the Simon&#8217;s surname is pronounced &#8216;Che&#8217;, so my hands were tied.</p>
<p><img alt="an IM icon created for a friend" src="http://www.jaysenmarais.com/blog_media/200707/simon_shea_large_green_96high.png"> <br /><em>an IM icon created for a friend (whose name is a homonym for che&#8217;s)</em></p>
<p>In the process I decided to&nbsp;adorn my IM profiles with the mighty &#8216;Pico&#8217; icon, something that had slipped my mind for years.</p>
<p><img alt="Pico icon" src="http://www.jaysenmarais.com/blog_media/200707/messenger_icon.gif">&nbsp;<br /><em>My new IM icon (based on my Pico character)</em></p>
<p>The original artwork dates is from the flash-based <a href="http://www.jaysenmarais.com/blog_media/200707/pico_game.swf">pico game</a> I made for a uni assignment at Hong Kong University in 2002.&nbsp;As&nbsp;I spent all my free (and a fair chunk of my uni) time exploring&nbsp;Hong Kong with my friends,&nbsp;the assignment&nbsp;was developed in a marathon 48 hour cram session in the&nbsp;HKU&nbsp;multimedia labs.&nbsp;</p>
<p><img alt="jaysen writing pico game in HKU CS labs" src="http://www.jaysenmarais.com/blog_media/200707/coding_pico.jpg"><br /><em>The game wasn&#8217;t always called Pico</em>&nbsp;</p>
<p>The game itself is a pretty basic affair, but still makes me laugh when I see the artwork and animations. As a bonus, it&#8217;s fiendishly difficult (being alone in a CS lab at 4am does tend to warp a coder&#8217;s mind). Give it a go, <a href="http://www.jaysenmarais.com/blog_media/200707/pico_game.swf">it&#8217;s a great cure for apathy</a>.</p>
<p><img src="http://www.jaysenmarais.com/blog_media/200707/hku_stairs.jpg">&nbsp;<br /><em>Hong Kong Island (including HKU) is an festival of stairs and elevators</em></p>
<p>The whole 2-day stint was surreal; the deadlines, the long walk along <a href="http://maps.google.com/maps?f=q&amp;hl=en&amp;geocode=&amp;q=hong+kong&amp;ie=UTF8&amp;ll=22.271405,114.131148&amp;spn=0.010822,0.023518&amp;t=h&amp;z=16&amp;om=1">pok fu lam road</a>, the long hours, the <a href="http://www.amazon.com/K-D-Sessions-Kruder-Dorfmeister/dp/B00000G257">great music</a>, the septuagenarian tai-chi club which trained (complete with weapons) right outside the labs at dawn (their existence was unknown to me previously and seems unreal still).</p>
<p><img src="http://www.jaysenmarais.com/blog_media/200707/pokfulam_road.jpg">&nbsp;<br /><em>Pok Fu Lam road, connecting HKU campus to the halls</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.jaysenmarais.com/blog/20070730/pico-redux/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hue City</title>
		<link>http://www.jaysenmarais.com/blog/20070617/hue-city</link>
		<comments>http://www.jaysenmarais.com/blog/20070617/hue-city#comments</comments>
		<pubDate>Sun, 17 Jun 2007 11:46:20 +0000</pubDate>
		<dc:creator>jaysen</dc:creator>
				<category><![CDATA[photography]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[colour]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[hue]]></category>
		<category><![CDATA[image search]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[quinton marais]]></category>
		<category><![CDATA[search]]></category>

		<guid isPermaLink="false">http://jaysenmarais.com/blog/20070617/hue-city/</guid>
		<description><![CDATA[A project that I&#8217;ve been working on forever has, among other features, a &#8216;search images by colour&#8216; feature. This is one that I&#8217;d been excited about for a long time and had tackled on several occasions but it had never quite come together. Until now. My previous attempts had all involved reducing each image to [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://www.quintonmarai.com">project</a> that I&#8217;ve been working on forever has, among other features, a &#8216;<a href="http://www.quintonmarais.com/search/colour.aspx">search images by colour</a>&#8216; feature. This is one that I&#8217;d been excited about for a long time and had tackled on several occasions but it had never quite come together. Until now.</p>
<p>My previous attempts had all involved reducing each image to a weighted list of &#8216;popular&#8217; colours. The search UI let the user pick from the <a href="http://en.wikipedia.org/wiki/Web_colors">web (216) palette</a>, with only images possessing a healthy portion of that colour being returned in the results. At one time I even allowed users to select a secondary colour along with <a href="http://en.wikipedia.org/wiki/RGB_color_space">RGB</a>/<a href="http://en.wikipedia.org/wiki/HSV_color_space">HSV</a>/<a href="http://en.wikipedia.org/wiki/CMYK_color_model">CMYK</a> (synchronised) sliders, but that was as complicated to use as it sounds, so I let it go. The problem was that this &#8216;popular colours&#8217; approach ignored the fundamental truth that people just don&#8217;t search for drab browns, faded yellowy-greens or most of the other colours which make up these palettes. From a colour-space perspective, when people say &#8216;colour&#8217;, they mean &#8216;<a href="http://en.wikipedia.org/wiki/Hue">hue</a>&#8216;. </p>
<p>So earlier this week (on the train) I set about re-writing the whole colour search feature to actually be a hue-based search feature (the word colour remains because &#8216;hue search&#8217; just doesn&#8217;t light up anyone&#8217;s eyes, not even mine). After a few train trips and most of Saturday I had the hue-parsing algorithm implemented and had written a console app which re-indexed all the existing images in the library. I also updated the relevant portions of the batch uploading tool and the admin web site to be hue-aware. Things were going well, but I had only a vague idea of how the actual search UI would work.</p>
<p>Initially I thought another slider would be the best approach,&nbsp;but decided it was overkill after looking around at&nbsp;existing html slider implementations (<a href="http://developer.yahoo.com/yui/slider/">yahoo UI library as a nice slider</a>, but I didn&#8217;t want the added dependency for what is essentially a minor feature). Eventually I&nbsp;set about&nbsp;rolling my own control for the job.&nbsp;I think the&nbsp;hue picker widget and the <a href="http://www.quintonmarais.com/search/colour.aspx">hue search feature</a> as a whole turned out really well, and will continue to improve as the number of images in the library grows.</p>
<p>Now I&#8217;m&nbsp;thinking of packaging&nbsp;up the &nbsp;Hue Picker for free distribution. You know, just for kicks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jaysenmarais.com/blog/20070617/hue-city/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>QuintonMarais.com launched tonight</title>
		<link>http://www.jaysenmarais.com/blog/20070613/quintonmaraiscom-launched-tonight</link>
		<comments>http://www.jaysenmarais.com/blog/20070613/quintonmaraiscom-launched-tonight#comments</comments>
		<pubDate>Wed, 13 Jun 2007 10:22:20 +0000</pubDate>
		<dc:creator>jaysen</dc:creator>
				<category><![CDATA[photography]]></category>
		<category><![CDATA[web development]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[discountasp.net]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[georss]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[quinton marais]]></category>
		<category><![CDATA[sql server]]></category>

		<guid isPermaLink="false">http://jaysenmarais.com/blog/20070613/quintonmaraiscom-launched-tonight/</guid>
		<description><![CDATA[After several weeks&#8217; work, quintonmarais.com launched this evening. Hi-lights include .Net 1.1 to .Net 2.0 upgrade (long live the MasterPage) Amazon S3 for all image storage (dramatically reduced bandwidth and hosting costs) Google map-based location search. Creation of &#8220;Pusher&#8221;, a fire-and-forget image watermarking, batch uploading and data-entry&#160;smart client app&#160;(to create the 12+ thumbnail and preview [...]]]></description>
			<content:encoded><![CDATA[<p>After several weeks&#8217; work, <a href="http://www.quintonmarais.com">quintonmarais.com</a> launched this evening.</p>
<p>Hi-lights include</p>
<ol>
<li>.Net 1.1 to .Net 2.0 upgrade (long live the MasterPage)
<li><a href="http://www.amazon.com/gp/browse.html?node=16427261">Amazon S3</a> for all image storage (dramatically reduced bandwidth and hosting costs)
<li><a href="http://maps.google.com/">Google map</a>-based <a href="http://www.quintonmarais.com/Search/Location.aspx">location search</a>.
<li>Creation of &#8220;Pusher&#8221;, a fire-and-forget image watermarking, batch uploading and data-entry&nbsp;smart client app&nbsp;(to create the 12+ thumbnail and preview versions of each image).
<li>Creation of &#8220;S3 Viewer&#8221;, a smart client app for viewing/maintaining the thousands of S3 items and buckets which support the site.
<li><a href="http://quintonmarais.com/Feeds/NewImages.ashx">&#8216;New Images&#8217;</a> atom feed (surprisingly easy to get going).
<li>SQL Server 2000 to SQL Server 2005 upgrade (<a href="http://msdn2.microsoft.com/en-us/library/ms186243(SQL.90).aspx">Common Table Expressions</a> are the goods).
<li><a href="http://georss.org/">GeoRSS</a> feed to (hopefully) ensure photographs appear in search results as geo-tagged objects.
<li><a href="http://www.quintonmarais.com">Tag-clouds</a> for hierarchical image categories.
<li><a href="http://quintonmarais.com/search/colour.aspx">Colour search</a> (still beta, currently rewriting the search algorithm to favour colour coverage rather than colour fidelity).
<li>Cleaner UI design.
<li>Xhtml transitional doc type with vastly improved markup validity (flash still causing some issues here). Some tables remain, to be slowly phased out when I have time.
<li>Flash 9 <a href="http://www.quintonmarais.com">homepage scroller</a> (flash cs3 didn&#8217;t play nice with my old flash 6 swfs).
<li>Self installed and configured SSL.
<li>New hosting provider (<a href="http://discountasp.net/">discountasp.net</a>, very impressed so far)</li>
</ol>
<p>All told the upgrade took about 3 months&#8217; worth of train trips, nights and weekends (around my day job). It&#8217;s meant an overall reduction in sleep, but ultimately worth it. Now I have just to force myself to stop tinkering with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jaysenmarais.com/blog/20070613/quintonmaraiscom-launched-tonight/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
