<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" version="2.0">
	<channel>
		<title>Articles &amp; Essays · Thomas J Bradley</title>
		<link>http://thomasjbradley.ca/</link>
		<description>Articles and essays written by Thomas J Bradley on topics including web development, web education, and Canadiana.</description>
		<docs>http://www.rssboard.org/rss-specification</docs>
		<language>en-ca</language>
		<pubDate>Thu, 17 May 2012 19:18:25 -0500</pubDate>
		<lastBuildDate>Thu, 17 May 2012 19:18:25 -0500</lastBuildDate>
		<atom:link href="http://thomasjbradley.ca/articles.xml" rel="self" type="application/rss+xml"/>
		<sy:updatePeriod>daily</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		
		<item>
			<title>Saving Signatures with PHP & MySQL</title>
			<link>http://thomasjbradley.ca/articles/saving-signatures-php-mysql</link>
			<pubDate>Sat, 11 Feb 2012 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/saving-signatures-php-mysql</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>A small PHP tutorial on how to capture the signature from Signature Pad and store it in a MySQL database, for later retrieval.</description>
			<content:encoded><![CDATA[<p><strong>A small PHP tutorial on how to capture the signature from Signature Pad and store it in a MySQL database, for later retrieval.</strong></p><div class="main-download">
  <ul class="files">
    <li class="zip"><a href="https://github.com/thomasjbradley/saving-signatures-sample/zipball/master" rel="enclosure"><i></i>Sample App <span>ZIP—GitHub</span></a></li>
  </ul>
</div>

<p><strong>This tutorial depends on Signature Pad. If you don’t know what that is go <a href="/lab/signature-pad/">check out Signature Pad, for capturing electronic signatures</a>.</strong></p>

<p><em>This tutorial is just a small overview of the important pieces of information from the downloadable sample application. <a href="https://github.com/thomasjbradley/saving-signatures-sample/">Check out the sample app itself</a>, there are lots of comments in the code to help you out.</em></p>

<h2 id="sampleapplicationfiles">Sample Application Files</h2>

<div class="highlight"><pre><code><b>saving-signatures-sample</b>/
 <small>|-</small> <i>index.php</i>
 <small>|-</small> <b>lib</b>/
 <small>|   |-</small> <i>save-signature.php</i>
 <small>|-</small> <b>views</b>/
 <small>|   |-</small> <i>accept.php</i>
 <small>|   |-</small> <i>regenerate.php</i>
 <small>|-</small> <b>signature-pad</b>/
 <small>|   |- …</small></code></pre></div>

<ul>
<li><code>index.php</code> contains the basic HTML template and a few <code>if-statements</code> to hide/show different pieces of HTML and Javascript.</li>
<li><code>lib/save-signature.php</code> is the meat and potatoes, the controller: it gets the content from the form, validates it, and saves it to the database.</li>
<li><code>views/accept.php</code> is the basic Signature Pad HTML template for <a href="/lab/signature-pad/#accept">accepting a signature</a>, with the addition of some serverside validation code.</li>
<li><code>views/regenerate.php</code> is the basic Signature Pad HTML template for <a href="/lab/signature-pad/#regenerate">regenerating a signature</a>, with the addition of a little PHP to output the signator and date.</li>
<li><code>signature-pad</code> is just a clone of the complete Signature Pad Git repository. The sample application only uses files from the <code>build</code> sub-folder.</li>
</ul>

<h2 id="gettingthesignature">Getting the Signature</h2>

<p>Signature Pad submits the signature, along with the rest of the form submission, inside a hidden input field.</p>

<p><em>From <code>views/accept.php</code>:</em></p>

<div class="highlight"><pre><code class="html"><span class="nt">&lt;form</span> <span class="na">method=</span><span class="s">&quot;post&quot;</span> <span class="na">action=</span><span class="s">&quot;index.php&quot;</span><span class="nt">&gt;</span>
  ⋮
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;hidden&quot;</span> <span class="na">name=</span><span class="s">&quot;output&quot;</span><span class="nt">&gt;</span>
  ⋮
<span class="nt">&lt;/form&gt;</span>
</code></pre>
</div>

<p>From this hidden field we can capture the signature and store it in the database.</p>

<p>The easiest way to get the signature using PHP is with the <code>$_POST</code> super global.</p>

<div class="highlight"><pre><code class="php"><span class="cp">&lt;?php</span>
<span class="nv">$sig</span> <span class="o">=</span> <span class="nv">$_POST</span><span class="p">[</span><span class="s1">&#39;output&#39;</span><span class="p">];</span>
</code></pre>
</div>

<p>Using the <code>$_POST</code> array isn’t secure (and creates a few other problems when there are validation errors and we try to keep information in the form). In PHP, the best way to get information from a form is using <a href="http://php.net/filter">PHP’s filter functions</a>. They provide a more secure way to grab user input and strip out unwanted information. We also won’t get any PHP error messages if we try to access the user input and the form hasn’t been submittted.</p>

<p><em>From <code>lib/save-signature.php</code>:</em></p>

<div class="highlight"><pre><code class="php"><span class="cp">&lt;?php</span>
<span class="nv">$output</span> <span class="o">=</span> <span class="nx">filter_input</span><span class="p">(</span><span class="nx">INPUT_POST</span><span class="p">,</span> <span class="s1">&#39;output&#39;</span><span class="p">,</span> <span class="nx">FILTER_UNSAFE_RAW</span><span class="p">);</span>
</code></pre>
</div>

<p>We can use <code>FILTER_UNSAFE_RAW</code> for the signature itself, because we don’t actually want to strip any information from the signature. If you want to be even more specific try using <code>FILTER_VALIDATE_REGEX</code>.</p>

<h2 id="validatingthesignature">Validating the Signature</h2>

<p>Probably the best way to validate the signature would be to run it through <code>json_decode()</code> and see if it can be decoded. </p>

<p><em>From <code>lib/save-signature.php</code>:</em></p>

<div class="highlight"><pre><code class="php"><span class="cp">&lt;?php</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">json_decode</span><span class="p">(</span><span class="nv">$output</span><span class="p">))</span> <span class="p">{</span>
  <span class="nv">$errors</span><span class="p">[</span><span class="s1">&#39;output&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>

<p><strong>Don’t forget, you should also validate the name to make sure one was entered.</strong></p>

<h2 id="settingupthedatabase">Setting Up the Database</h2>

<p>The database to store the signature only needs to hold a few pieces of information: the signator’s name and the signature. For legal reasons, it is best to store more information about the signature: at least a hash of the signature, the signator’s IP address, and the time the signature was written.</p>

<p>For more information about electronic signature legallity, check out your country’s regulations. <a href="http://en.wikipedia.org/wiki/Electronic_signature">Wikipedia has a good list of electronic signature regulations</a>.</p>

<h3 id="sampletablesetup">Sample Table Setup</h3>

<table>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Data-Type</th>
      <th scope="col">Length</th>
      <th scope="col">What’s it For?</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>id</td>
      <td>int</td>
      <td>11</td>
      <td>Primary key, auto increment</td>
    </tr>
    <tr>
      <td>signator</td>
      <td>varchar</td>
      <td>255</td>
      <td>Holds the user input for the `name` field</td>
    </tr>
    <tr>
      <td>signature</td>
      <td>text</td>
      <td></td>
      <td>Holds the signature in its JSON form</td>
    </tr>
    <tr>
      <td>sig_hash</td>
      <td>varchar</td>
      <td>128</td>
      <td>Holds a SHA1 hash of the JSON signature</td>
    </tr>
    <tr>
      <td>ip</td>
      <td>varchar</td>
      <td>46</td>
      <td>Holds the signator’s IP address</td>
    </tr>
    <tr>
      <td>created</td>
      <td>int</td>
      <td>11</td>
      <td>The UNIX timestamp of when the signature was saved</td>
    </tr>
  </tbody>
</table>

<h2 id="savingtothedatabase">Saving to the Database</h2>

<p>After everything is validated, we can save the signature to the database. It’s easiest to just store the JSON representation of the signature in the database. If you want to create a graphic file, <a href="/lab/signature-pad/#images">check out how to convert the signature to an image</a>.</p>

<p>It’s best to use PHP’s <a href="http://php.net/pdo">PDO</a> for connecting to databases. By using <code>PDO::prepare()</code>, we can help protect against SQL injection attacks.</p>

<p><em>From <code>lib/save-signature.php</code>:</em></p>

<div class="highlight"><pre><code class="php"><span class="cp">&lt;?php</span>
<span class="c1">// Open the database connection</span>
<span class="nv">$db</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">PDO</span><span class="p">(</span><span class="nv">$dsn</span><span class="p">,</span> <span class="nv">$user</span><span class="p">,</span> <span class="nv">$pass</span><span class="p">);</span>
<span class="c1">// Make sure we are talking to the database in UTF-8</span>
<span class="nv">$db</span><span class="o">-&gt;</span><span class="na">exec</span><span class="p">(</span><span class="s1">&#39;SET NAMES utf8&#39;</span><span class="p">);</span>

<span class="c1">// Create some other pieces of information about the user</span>
<span class="c1">//  to confirm the legitimacy of their signature</span>
<span class="nv">$sig_hash</span> <span class="o">=</span> <span class="nb">sha1</span><span class="p">(</span><span class="nv">$output</span><span class="p">);</span>
<span class="nv">$created</span> <span class="o">=</span> <span class="nb">time</span><span class="p">();</span>
<span class="nv">$ip</span> <span class="o">=</span> <span class="nv">$_SERVER</span><span class="p">[</span><span class="s1">&#39;REMOTE_ADDR&#39;</span><span class="p">];</span>

<span class="c1">// Use PDO prepare to insert all the information into the database</span>
<span class="nv">$sql</span> <span class="o">=</span> <span class="nv">$db</span><span class="o">-&gt;</span><span class="na">prepare</span><span class="p">(</span><span class="s1">&#39;</span>
<span class="s1">  INSERT INTO signatures (signator, signature, sig_hash, ip, created)</span>
<span class="s1">  VALUES (:signator, :signature, :sig_hash, :ip, :created)</span>
<span class="s1">&#39;</span><span class="p">);</span>
<span class="nv">$sql</span><span class="o">-&gt;</span><span class="na">bindValue</span><span class="p">(</span><span class="s1">&#39;:signator&#39;</span><span class="p">,</span> <span class="nv">$name</span><span class="p">,</span> <span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_STR</span><span class="p">);</span>
<span class="nv">$sql</span><span class="o">-&gt;</span><span class="na">bindValue</span><span class="p">(</span><span class="s1">&#39;:signature&#39;</span><span class="p">,</span> <span class="nv">$output</span><span class="p">,</span> <span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_STR</span><span class="p">);</span>
<span class="nv">$sql</span><span class="o">-&gt;</span><span class="na">bindValue</span><span class="p">(</span><span class="s1">&#39;:sig_hash&#39;</span><span class="p">,</span> <span class="nv">$sig_hash</span><span class="p">,</span> <span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_STR</span><span class="p">);</span>
<span class="nv">$sql</span><span class="o">-&gt;</span><span class="na">bindValue</span><span class="p">(</span><span class="s1">&#39;:ip&#39;</span><span class="p">,</span> <span class="nv">$ip</span><span class="p">,</span> <span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_STR</span><span class="p">);</span>
<span class="nv">$sql</span><span class="o">-&gt;</span><span class="na">bindValue</span><span class="p">(</span><span class="s1">&#39;:created&#39;</span><span class="p">,</span> <span class="nv">$created</span><span class="p">,</span> <span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_INT</span><span class="p">);</span>
<span class="nv">$sql</span><span class="o">-&gt;</span><span class="na">execute</span><span class="p">();</span>
</code></pre>
</div>

<h2 id="regeneratingthesignature">Regenerating the Signature</h2>

<p>One of the easiest ways to regenerate the signature is to use PHP to write out some Javascript onto one of your pages. When the page loads it will have a native Javascript varible containing all the signature information and can use Signature Pad to regenerate the display.</p>

<div class="highlight"><pre><code class="html"><span class="nt">&lt;script&gt;</span>
  <span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">ready</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="c1">// Write out the complete signature from the database to Javascript</span>
    <span class="kd">var</span> <span class="nx">sig</span> <span class="o">=</span> <span class="o">&lt;?</span><span class="nx">php</span> <span class="nx">echo</span> <span class="nx">$output</span><span class="p">;</span> <span class="o">?&gt;</span><span class="p">;</span>
    <span class="nx">$</span><span class="p">(</span><span class="s1">&#39;.sigPad&#39;</span><span class="p">).</span><span class="nx">signaturePad</span><span class="p">({</span><span class="nx">displayOnly</span> <span class="o">:</span> <span class="kc">true</span><span class="p">}).</span><span class="nx">regenerate</span><span class="p">(</span><span class="nx">sig</span><span class="p">);</span>
  <span class="p">});</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre>
</div>

<h2 id="whatelsedoweneed">What Else Do We Need?</h2>

<p>Well, this application is far from complete—even though it’s fully functional. It’s a simple tutorial on how to capture the signature. Some of the missing things are:</p>

<ol>
<li>User authentication, sign-in/sign-out, or unique passkeys.</li>
<li>HTTPS—critical for capturing signatures online.</li>
<li>It might be nice to encrypt the signatures in the database.</li>
</ol>

<p>And likely more.</p>

<h2 id="downloadtheapp">Download the App</h2>

<p><a href="https://github.com/thomasjbradley/saving-signatures-sample">Download the sample app on GiHub</a></p>]]></content:encoded>
		</item>
		
		<item>
			<title>Marking Up Code for the Ambitious</title>
			<link>http://thomasjbradley.ca/articles/marking-up-code-for-ambitious</link>
			<pubDate>Mon, 11 Apr 2011 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/marking-up-code-for-ambitious</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>Code markup in online content and documentation can be improved. Here’s a proposal for the ambitious semanticists out there.</description>
			<content:encoded><![CDATA[<p><strong>Code markup in online content and documentation can be improved. Here’s a proposal for the ambitious semanticists out there.</strong></p><p>As web developers we write a lot of code, we also take the time to properly select the most semantically appropriate HTML elements for our content. When writing tutorials and articles with code, why don’t we also take the time to properly mark up our code samples in HTML?</p>

<p>Most developers take the route of using a Javascript syntax highlighter or using a server side solution, like <a href="http://pygments.org/">Pygments</a>. These aren’t bad solutions, in fact they are pretty great, but they just use a bunch of <code class="language-html">&lt;<b>span</b>&gt;</code> elements with classes to syntax highlight. We can do better, semantically.</p>

<h2 id="theelements">The Elements</h2>

<p>We still need to use the trusty <code class="language-html">&lt;<b>pre</b>&gt;&lt;<b>code</b>&gt;</code> as used by the above mentioned scripts. But for the code inside, we can do so much better than meaningless <code class="language-html">&lt;<b>span</b>&gt;</code>s.</p>

<p>Looking at the HTML specification we have a bunch of elements that make sense within our code blocks:</p>

<ul>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-var-element" rel="external"><b>var</b></a>&gt;</code>: variables</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-b-element" rel="external"><b>b</b></a>&gt;</code>: keywords; like built in functions and properties</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-i-element" rel="external"><b>i</b></a>&gt;</code>: taxonomy, technical term, designation; like properties, methods, attributes</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-small-element" rel="external"><b>small</b></a>&gt;</code>: fine print or comments</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#the-del-element" rel="external"><b>del</b></a>&gt;</code>: code that is removed</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#the-ins-element" rel="external"><b>ins</b></a>&gt;</code>: code that is added</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-mark-element" rel="external"><b>mark</b></a>&gt;</code>: important, highlighted code</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-samp-element" rel="external"><b>samp</b></a>&gt;</code>: computer output</li>
<li><code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-kbd-element" rel="external"><b>kbd</b></a>&gt;</code>: user input</li>
</ul>

<p>And we still use the <code class="language-html">&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-span-element" rel="external"><b>span</b></a>&gt;</code>, but only for things that have no meaning in the context, like a regular old string.</p>

<h2 id="someexamples">Some Examples</h2>

<p>Lets walk through some samples to see how to use these elements in our code samples.</p>

<h3 id="html">HTML</h3>

<p><strong>What you want to see:</strong><br><small>(view source to see it in practice)</small></p>

<div class="highlight">
<pre><code class="code-block language-html">&lt;<b>div</b> <i>class</i>=<span>"group"</span>&gt;
&lt;<b>h1</b>&gt;Sample HTML&lt;/<b>h1</b>&gt;
&lt;<b>p</b>&gt;Some super awesome content!&lt;/<b>p</b>&gt;
&lt;/<b>div</b>&gt;<small>&lt;!-- end group --&gt;</small></code></pre>
</div>

<p><strong>What HTML you would write:</strong></p>

<div class="highlight">
<pre><code class="code-block language-html"><i>&amp;lt;</i>&lt;<b>b</b>&gt;div&lt;/<b>b</b>&gt; &lt;<b>i</b>&gt;class&lt;/<b>i</b>&gt;=&lt;<b>span</b>&gt;"group"&lt;/<b>span</b>&gt;<i>&amp;gt;</i>
<i>&amp;lt;</i>&lt;<b>b</b>&gt;h1&lt;/<b>b</b>&gt;<i>&amp;gt;</i>Sample HTML<i>&amp;lt;</i>/&lt;<b>b</b>&gt;h1&lt;/<b>b</b>&gt;<i>&amp;gt;</i>
<i>&amp;lt;</i>&lt;<b>b</b>&gt;p&lt;/<b>b</b>&gt;<i>&amp;gt;</i>Some super awesome content!<i>&amp;lt;</i>/&lt;<b>b</b>&gt;p&lt;/<b>b</b>&gt;<i>&amp;gt;</i>
<i>&amp;lt;</i>/&lt;<b>b</b>&gt;div&lt;/<b>b</b>&gt;<i>&amp;gt;</i>&lt;<b>small</b>&gt;<i>&amp;lt;</i>!-- end group --<i>&amp;gt;</i>&lt;/<b>small</b>&gt;</code></pre>
</div>

<p>So, from a semantics point of view, I believe the above code is more appropriate. The notable additions are:</p>

<ul>
<li><code class="language-html">&lt;<b>b</b>&gt;</code> for wrapping around the HTML elements; semantically the elements are keywords, in their context.</li>
<li><code class="language-html">&lt;<b>i</b>&gt;</code> for wrapping attributes on the HTML elements; I suppose that attributes are a taxonomies or designations.</li>
<li><code class="language-html">&lt;<b>span</b>&gt;</code> for wrapping around strings in code, since the string really doesn’t have any meaning.</li>
<li><code class="language-html">&lt;<b>small</b>&gt;</code> for wrapping around comments.</li>
</ul>

<h2 id="css">CSS</h2>

<p><strong>What you want to see:</strong><br><small>(view source to see it in practice)</small></p>

<div class="highlight">
<pre><code class="code-block language-css"><small>/* Sectioning Elements */</small>
<i>.group</i> {
  <b>background-image</b>: url(<span>"pattern.png"</span>);
  <b>border</b>: 1px <b>solid</b> #000;
}</code></pre>
</div>

<p><strong>What HTML you would write:</strong></p>

<div class="highlight">
<pre><code class="code-block language-html">&lt;<b>small</b>&gt;/* Sectioning Elements */&lt;/<b>small</b>&gt;
&lt;<b>i</b>&gt;.group&lt;/<b>i</b>&gt; {
  &lt;<b>b</b>&gt;background-image&lt;/<b>b</b>&gt;: url(&lt;<b>span</b>&gt;"pattern.png"&lt;/<b>span</b>&gt;);
  &lt;<b>b</b>&gt;border&lt;/<b>b</b>&gt;: 1px &lt;<b>b</b>&gt;solid&lt;/<b>b</b>&gt; #000;
}</code></pre>
</div>

<p>The same sorta rules apply for CSS, <code class="language-html">&lt;<b>b</b>&gt;</code> for keywords, aka properties; <code class="language-html">&lt;<b>i</b>&gt;</code> for selectors; <code class="language-html">&lt;<b>span</b>&gt;</code> for strings; and, of course, <code class="language-html">&lt;<b>small</b>&gt;</code> for comments.</p>

<h3 id="javascript">Javascript</h3>

<p>Let’s look at something a little more complex for Javascript, including additions and deletions and important parts.</p>

<p><strong>What you want to see:</strong><br><small>(view source to see it in practice)</small></p>

<div class="highlight">
<pre><code class="code-block language-javascript"><b>document</b>.<i>getElementById</i>(<span>'foo'</span>).<i>addEventListener</i>(<span>'click'</span>, <b>function</b>(<var>evt</var>)
{
<b>var</b> <var>myMessage</var> = <span>'Hello World!'</span>;

<del><b>alert</b>(<var>myMessage</var>)</del>
<ins><mark><b>console</b>.<i>log</i>(<var>myMessage</var>)</mark></ins>
}, <b>false</b>)</code></pre>
</div>

<p><strong>What HTML you would write:</strong></p>

<div class="highlight">
<pre><code class="code-block language-html">&lt;<b>b</b>&gt;document&lt;/<b>b</b>&gt;.&lt;<b>i</b>&gt;getElementById&lt;/<b>i</b>&gt;(&lt;<b>span</b>&gt;'foo'&lt;/<b>span</b>&gt;).&lt;<b>i</b>&gt;addEventListener&lt;/<b>i</b>&gt;(&lt;<b>span</b>&gt;'click'&lt;/<b>span</b>&gt;, &lt;<b>b</b>&gt;function&lt;/<b>b</b>&gt;(&lt;<b>var</b>&gt;evt&lt;/<b>var</b>&gt;)
{
&lt;<b>b</b>&gt;var&lt;/<b>b</b>&gt; &lt;<b>var</b>&gt;myMessage&lt;/<b>var</b>&gt; = &lt;<b>span</b>&gt;'Hello World!'&lt;/<b>span</b>&gt;;

&lt;<b>del</b>&gt;&lt;<b>b</b>&gt;alert&lt;/<b>b</b>&gt;(&lt;<b>var</b>&gt;myMessage&lt;/<b>var</b>&gt;)&lt;/<b>del</b>&gt;
&lt;<b>ins</b>&gt;&lt;<b>mark</b>&gt;&lt;<b>b</b>&gt;console&lt;/<b>b</b>&gt;.&lt;<b>i</b>&gt;log&lt;/<b>i</b>&gt;(&lt;<b>var</b>&gt;myMessage&lt;/<b>var</b>&gt;)&lt;/<b>mark</b>&gt;&lt;/<b>ins</b>&gt;
}, &lt;<b>b</b>&gt;false&lt;/<b>b</b>&gt;)</code></pre>
</div>

<p>A few notable additions are the use of <code class="language-html">&lt;<b>var</b>&gt;</code> for wrapping around variables and arguments. The example uses <code class="language-html">&lt;<b>b</b>&gt;</code> around Javascript keywords; for <code class="language-javascript"><b>document</b></code> and <code class="language-javascript"><b>console</b></code>, it may be more technically correct to wrap them in <code class="language-html">&lt;<b>var</b>&gt;</code> elements, but I like to reserve <code class="language-html">&lt;<b>var</b>&gt;</code> for variables and arguments I have created.</p>

<p>When marking up objects and their properties, I feel that it’s more appropriate to mark up the parent as a <code class="language-html">&lt;<b>b</b>&gt;</code> or <code class="language-html">&lt;<b>var</b>&gt;</code> and all the child properties/functions as <code class="language-html">&lt;<b>i</b>&gt;</code> elements, as in <code class="language-javascript"><b>document</b>.<i>getElementById</i>()</code>.</p>

<p>Since the above code example is kinda like a tutorial, I decided to show that <code class="language-html">&lt;<b>del</b>&gt;</code> and <code class="language-html">&lt;<b>ins</b>&gt;</code> can be used to demonstrate code that should be deleted and code that should be inserted.</p>

<p>Using the <code class="language-html">&lt;<b>mark</b>&gt;</code> element we can highlight as passage of code that is important to the current step in the tutorial.</p>

<h3 id="php">PHP</h3>

<p>What about going even further by integrating documentation with our code samples by linking to further resources.</p>

<p><strong>What you want to see:</strong><br><small>(view source to see it in practice)</small></p>

<div class="highlight">
<pre><code class="code-block language-php"><small>&lt;?php</small>

<var>$db</var> = <b>new</b> <a href="http://php.net/pdo" rel="external"><b>PDO</b></a>(<span>'mysql:dbname=mydb;host=localhost'</span>, <span>'root'</span>, <span>''</span>);
<var>$db</var>-><a href="http://php.net/pdo.exec" rel="external"><i>exec</i></a>(<span>'DELETE FROM mytable'</span>);</code></pre>
</div>

<p><strong>What HTML you would write:</strong></p>

<div class="highlight">
<pre><code class="code-block language-html">&lt;<b>small</b>&gt;<i>&amp;lt;</i>?php&lt;<b>small</b>&gt;

&lt;<b>var</b>&gt;$db&lt;/<b>var</b>&gt; = &lt;<b>b</b>&gt;new&lt;/<b>b</b>&gt; &lt;<b>a</b> <i>href</i>=<span>"http://php.net/pdo"</span>&gt;&lt;<b>b</b>&gt;PDO&lt;/<b>b</b>&gt;&lt;/<b>a</b>&gt;(&lt;<b>span</b>&gt;'mysql:dbname=mydb;host=localhost'&lt;/<b>span</b>&gt;, &lt;<b>span</b>&gt;'root'&lt;/<b>span</b>&gt;, &lt;<b>span</b>&gt;''&lt;/<b>span</b>&gt;);
&lt;<b>var</b>&gt;$db&lt;/<b>var</b>&gt;-<i>&amp;gt;</i>&lt;<b>a</b> <i>href</i>=<span>"http://php.net/pdo.exec"</span>&gt;&lt;<b>i</b>&gt;exec&lt;/<b>i</b>&gt;&lt;/<b>a</b>&gt;(&lt;<b>span</b>&gt;'DELETE FROM mytable'&lt;/<b>span</b>&gt;);</code></pre>
</div>

<p>Since the above sample is teaching about PDO and <code class="language-php"><i>exec</i>()</code>, why not link those functions to the PHP documentation, then readers can jump into deeper material at their discretion.</p>

<h3 id="terminal">Terminal</h3>

<p>I’m not going to cover using <code class="language-html">&lt;<b>samp</b>&gt;</code> and <code class="language-html">&lt;<b>kbd</b>&gt;</code> because the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#the-samp-element" title="Exmaples of using the &lt;kbd&gt; and &lt;samp&gt; elements" rel="external">HTML spec has some great examples.</a></p>

<h2 id="definingthelanguage">Defining the Language</h2>

<p>There is a <a href="http://stackoverflow.com/questions/5134242/sematics-standards-and-using-the-lang-attribute-for-source-code-in-markup">great question on Stack Overflow</a> about what is the most semantically appropriate way to define the programming language for the code. I’m a fan of using <code class="language-html"><i>@class</i></code>, like so:</p>

<div class="highlight">
<pre><code class="code-block language-html">&lt;<b>pre</b>&gt;&lt;<b>code</b> <i>class</i>=<span>"language-html"</span>&gt;…&lt;/<b>code</b>&gt;&lt;/<b>pre</b>&gt;</code></pre>
</div>

<h2 id="whybother">Why Bother?</h2>

<p>Well, I recognize many developers are lazy. And I recognize that the automated solutions have extra benefits such as copy-friendly versions and line numbers, etc. But code seems to be one of those places in online content and documentation where markup can be improved. It seems that web developers spend time choosing appropriate elements for general content, then just dump the code onto the page. True craftsmen would sweat all the details.</p>

<p>Am I over-the-top semantic crazy? Likely. But semantics and code are what we do, lets spend a little more time on our documentation samples.</p>]]></content:encoded>
		</item>
		
		<item>
			<title>Park Finder: A Mobile First Application</title>
			<link>http://thomasjbradley.ca/articles/park-finder-mobile-first-app</link>
			<pubDate>Thu, 24 Feb 2011 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/park-finder-mobile-first-app</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>A small, location-based application using Ottawa’s open data and mobile first ideas.</description>
			<content:encoded><![CDATA[<p><strong>A small, location-based application using Ottawa’s open data and mobile first ideas.</strong></p><h2 id="alittlehistorylldoyagood">A little history’ll do ya good</h2>

<p>The <a href="http://parkfinder.ottawadogblog.ca/">Ottawa Dog Park Finder</a> was originally created for the <a href="http://opendataottawa.ca/">Ottawa Open Data</a> movement to show to the city what is possible. <a href="/articles/open-data-ottawa">Read more about the original process in the Open Data blog post.</a>) But, it was also created to help Ottawa dog owners find the best parks in the city.</p>

<p>There was one feature that I felt was missing from Park Finder since it launched: a mobile version. When the <a href="http://ottawa.ca/">City of Ottawa</a> decided to host an <a href="http://apps4ottawa.ca/">application contest for Open Data apps</a> I decided to enter Park Finder, but first make it mobile ready.</p>

<h2 id="theopenwebplatform">The open web platform</h2>

<p>I’m a web developer at heart and don’t have much interest in doing native applications, so the only logical choice was to make a mobile web app. The concept of <a href="http://www.lukew.com/ff/entry.asp?933">Mobile First</a> is exactly the solution I wanted. The idea behind Mobile First, a concept envisioned by <a href="http://www.lukew.com/">Luke Wroblewski</a>, was to design for mobile—first—then design for other platforms. Forcing designers to determine what features are really important.</p>

<p>Though, we shouldn’t stop at design with Mobile First; when creating web sites and web applications, the same ideas can be applied to code. Why not default to mobile, then if conditions are right, expand to desktop versions. That’s exactly what I did when re-developing Park Finder in December.</p>

<h2 id="thesupporteddevices">The supported devices</h2>

<p>My goal from the start was to make the app browser agnostic (the goal of any <em>real</em> web developer). So, <a href="/articles/mobile-testing-suite/">using my mobile testing suite</a>, I set out to make Park Finder work on all those devices.</p>

<p>The project was a success, I was able to support all the browsers listed in my mobile testing suite (forget BB OS 4, it sucks!) and all the major desktop browsers.</p>

<p>In the spirit of Mobile First, and mobile in general, I simplified the application on mobile to just the essentials:</p>

<ul>
<li>displaying the parks nearest you (geo-location, please);</li>
<li>searching for a park;</li>
<li>and rating parks.</li>
</ul>

<p>The only major feature that was removed was park filtering.</p>

<p>The original application was a one page app, clicking on parks just displayed them on the Google Map. Since I needed to support mobiles without Google Maps, the app turned into a multi-page app (as it should have been from the beginning) and used <a href="http://code.google.com/apis/maps/documentation/staticmaps/">Google Static Maps</a> for the geo-location functionality.</p>

<h3 id="deviceclassification">Device classification</h3>

<p>I segregated devices into a few classifications: basic, enhanced and enhanced wide. Basic includes all mobile phones and IE 6. Enhanced includes tablet size devices and screens with widths less than 1000 px. Enhanced wide includes all larger screens.</p>

<p>I had originally planned to put Google Maps onto the mobile phones that supported it (Android, iPhone, BB OS 6, Bada), but the usability just wasn’t as great as I had hoped, so Google Maps got relegated to enhanced and enhanced wide only devices (tablets and desktops).</p>

<h2 id="technicalsetup">Technical set up</h2>

<p>The general idea was to send the basic version of the site to all browsers to minimize download time (and because I am not the biggest fan of browser sniffing). Then using <a href="http://www.modernizr.com/">Modernizr</a> and a few other techniques, dynamically load the other resources as required.</p>

<h3 id="theloadingprocess">The loading process</h3>

<h4 id="basic">1. Basic</h4>

<ul>
<li>HTML, <code>basic.css</code>, <code>basic.js</code>, Modernizr, <a href="http://code.google.com/p/geo-location-javascript/">Geo.js</a></li>
<li><strong>No Javascript frameworks for basic, too heavy.</strong></li>
</ul>

<h4 id="enhanced">2. Enhanced</h4>

<ul>
<li><strong>Only executed if the browser supports Google Maps</strong></li>
<li>Dynamically include <code>enhanced.css</code> and <code>enhanced-wide.css</code> (with <code>@media min-width: 1000px</code>)</li>
<li>Dynamically include Google Maps</li>
<li>Dynamically include <code>enhanced.min.js</code>, a bunch of Javascript files minified together to preserve loading order <a href="http://jquery.com">jQuery</a>, <a href="http://code.google.com/p/google-maps-utility-library-v3/">Marker Manager</a>, <a href="http://www.movable-type.co.uk/scripts/latlong.html">LatLng</a>, <code>enhanced.js</code>)</li>
</ul>

<h4 id="enhancedwide">3. Enhanced wide</h4>

<ul>
<li>Enhanced wide does not have any feature differences than enhanced, it only looks different: parks are listed beside the map instead of below.</li>
</ul>

<h3 id="somecodebits">Some code bits</h3>

<p>There were a couple other things I needed to detect to fully support my Mobile First idea.</p>

<h4 id="modernizr.xhr">Modernizr.xhr</h4>

<p>A Modernizr test to check for XMLHttpRequest support. Used to distinguish between desktop IE 6 and Windows Mobile 6.5 IE 6.</p>

<div class="highlight"><pre><code class="js"><span class="nx">Modernizr</span><span class="p">.</span><span class="nx">addTest</span><span class="p">(</span><span class="s1">&#39;xhr&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
  <span class="k">return</span> <span class="o">!</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">XMLHttpRequest</span> <span class="o">==</span> <span class="s1">&#39;undefined&#39;</span><span class="p">);</span>
<span class="p">});</span>
</code></pre>
</div>

<h4 id="modernizr.mediaqueries">Modernizr.mediaqueries</h4>

<p>A Modernizr test to check for very basic media query support. <strong>As of Modernizr version 2, similar code is already included.</strong></p>

<div class="highlight"><pre><code class="js"><span class="nx">Modernizr</span><span class="p">.</span><span class="nx">addTest</span><span class="p">(</span><span class="s1">&#39;mediaqueries&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">ret</span> <span class="o">=</span> <span class="kc">false</span>
    <span class="p">,</span> <span class="nx">test</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;div&#39;</span><span class="p">)</span>
    <span class="p">,</span> <span class="nx">styles</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;style&#39;</span><span class="p">)</span>
    <span class="p">,</span> <span class="nx">styledef</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createTextNode</span><span class="p">(</span><span class="s1">&#39;#modernizr-mq-tester{top:-999em;position:absolute;display:none;} @media screen and (min-width:5px){#modernizr-mq-tester{display:block;}}&#39;</span><span class="p">)</span>
    <span class="p">,</span> <span class="nx">head</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">[</span><span class="s1">&#39;head&#39;</span><span class="p">](</span><span class="mi">0</span><span class="p">)</span>
  <span class="p">;</span>

  <span class="nx">test</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="s1">&#39;modernizr-mq-tester&#39;</span><span class="p">;</span>
  <span class="nx">test</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="s1">&#39;&amp;nbsp;&#39;</span><span class="p">;</span>
  <span class="nx">styles</span><span class="p">.</span><span class="nx">id</span> <span class="o">=</span> <span class="s1">&#39;modernizr-mq-styles&#39;</span><span class="p">;</span>

  <span class="k">try</span> <span class="p">{</span>
    <span class="nx">styles</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">styledef</span><span class="p">);</span>
    <span class="nx">head</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">styles</span><span class="p">);</span>
    <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">test</span><span class="p">);</span>
    <span class="nx">ret</span> <span class="o">=</span> <span class="nx">getComputedStyle</span><span class="p">(</span><span class="nx">test</span><span class="p">,</span> <span class="kc">null</span><span class="p">).</span><span class="nx">getPropertyValue</span><span class="p">(</span><span class="s1">&#39;display&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s1">&#39;block&#39;</span><span class="p">;</span>
    <span class="nx">head</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">styles</span><span class="p">);</span>
    <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">test</span><span class="p">);</span>
  <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{}</span>

  <span class="k">return</span> <span class="nx">ret</span><span class="p">;</span>
<span class="p">});</span>
</code></pre>
</div>

<h4 id="modernizr.googlemaps">Modernizr.googlemaps</h4>

<p>Though not completely accurate, used to detect Google Map support on devices. The code below doesn’t detect mobile phones because it’s looking for a minimum width of 660 px; just change that to 320 px for phone support.</p>

<div class="highlight"><pre><code class="js"><span class="nx">Modernizr</span><span class="p">.</span><span class="nx">addTest</span><span class="p">(</span><span class="s1">&#39;googlemaps&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">cw</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">clientWidth</span>
    <span class="p">,</span> <span class="nx">isIE7</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">className</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;ie7&#39;</span><span class="p">)</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span>
    <span class="p">,</span> <span class="nx">isIE8</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">className</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;ie8&#39;</span><span class="p">)</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span>
    <span class="p">,</span> <span class="nx">isIEMobile</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">className</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;ie7mobile&#39;</span><span class="p">)</span> <span class="o">&gt;</span> <span class="o">-</span><span class="mi">1</span>
  <span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span><span class="nx">cw</span> <span class="o">&lt;</span> <span class="mi">600</span> <span class="o">||</span> <span class="o">!</span><span class="nx">Modernizr</span><span class="p">.</span><span class="nx">xhr</span> <span class="o">||</span> <span class="nx">isIEMobile</span><span class="p">)</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>

  <span class="k">if</span> <span class="p">(</span>
    <span class="p">(</span><span class="nx">cw</span> <span class="o">&lt;</span> <span class="mi">780</span> <span class="o">&amp;&amp;</span> <span class="nx">Modernizr</span><span class="p">.</span><span class="nx">touch</span> <span class="o">&amp;&amp;</span> <span class="nx">Modernizr</span><span class="p">.</span><span class="nx">mediaqueries</span><span class="p">)</span>
    <span class="o">||</span> <span class="p">(</span><span class="nx">cw</span> <span class="o">&gt;=</span> <span class="mi">780</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="nx">Modernizr</span><span class="p">.</span><span class="nx">mediaqueries</span> <span class="o">||</span> <span class="nx">isIE8</span> <span class="o">||</span> <span class="nx">isIE7</span><span class="p">))</span>
  <span class="p">)</span> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>

  <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">});</span>
</code></pre>
</div>

<h2 id="thefinalapp">The final app</h2>

<p>I’m very happy with the final application, it turned out amazing. I’m super excited because <strong>I won bronze in my category in the <a href="http://apps4ottawa.ca/">Apps4Ottawa</a> competition</strong>!</p>

<h3 id="acoupleniggles">A couple niggles</h3>

<p>I’m not the biggest fan of the flash that happens just before the enhanced wide layout displays. I think the solution is to detect enhanced wide using media queries inside <code>basic.css</code> and hide the whole application, then after <code>enhanced-wide.css</code> is loaded, fade the application back in.</p>

<p>Also, since the app is now a many-page application, when you load a specific park’s URL in a desktop browser it should immediately show it in Google Maps, but does not.</p>

<h2 id="thefutureformobilefirst">The future for Mobile First</h2>

<p>This technique works great for many web sites. Where the most important information is sent as a basic package, then detect features client side, and, if required, dynamically load other assets. Think about a site with a heavy sidebar: don’t send the sidebar to mobile, but AJAX it in for desktop clients.</p>

<p>This mobile first idea, coupled with responsive design, is the way forward for many sites and is what I am exploring on all my future projects.</p>]]></content:encoded>
		</item>
		
		<item>
			<title>Mobile Testing Suite</title>
			<link>http://thomasjbradley.ca/articles/mobile-testing-suite</link>
			<pubDate>Fri, 26 Nov 2010 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/mobile-testing-suite</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>Since the mobile internet is growing at an extremely quick pace I felt it was prudent to start testing/developing sites on mobile devices.</description>
			<content:encoded><![CDATA[<p><strong>Since the mobile internet is growing at an extremely quick pace I felt it was prudent to start testing/developing sites on mobile devices.</strong></p><p>I started by downloading a bunch of emulators including Android, WebOS, BlackBerry and Windows Phone 7. But quickly found limitations to this approach.</p>

<p>The main limitation of the emulators is that they can’t be open at the same time as my virtual versions of IE. Another issue I quickly found was the lack of Nokia emulators and since Nokia is the most popular handset maker in the world, this is a major issue. I did find the <a href="http://www.developer.nokia.com/Devices/Remote_device_access/">Nokia Remote Device Access</a>, but the idea of scheduling a time and waiting wasn’t something I was excited about.</p>

<p>And we all know that emulators are far from perfect, so actual devices are what I needed.</p>

<h2 id="researchingthephones">Researching the Phones</h2>

<p>I have been <a href="http://www.quirksmode.org/blog/">reading a lot of articles</a>, <a href="http://www.lukew.com/ff/entry.asp?1137">watching a lot videos</a> and <a href="http://www.slideshare.net/bryanrieger/rethinking-the-mobile-web-by-yiibu">clicking through a lot of slideshows</a> trying to wrap my head around the extremely complex and fractured mobile web market.</p>

<p>One article that was extremely helpful was ‘<a href="http://yiibu.com/articles/practical-guide-to-nokia-browsers/">A Practical Guide to Nokia Browsers</a>’ which is a great overview and explanation of the different Symbian browser versions and gives a smattering of Nokia phones that would be good for testing.</p>

<p>The rest of the mobile market isn’t as difficult to handle, assuming that you rule out a bunch of feature phones that people don’t likely surf the internet on anyways; but if they do, they are crazy.</p>

<p>I compiled a list of the browsers and operating systems that I wanted to support and from that determined what phones to get. It took a lot of comparing phone specifications and looking around online to find devices for sale (four days to be exact) to find the phones that would fit into my test suite.</p>

<p>I didn’t want to spend too much money, so I was always conscious of the prices. Continued cost was also very important and I didn’t want to have to support multiple mobile data plans. All of the phones I have in my test suite, therefore, are WiFi equipped.</p>

<h2 id="listofbrowsersossphones">List of Browsers, OSs, Phones</h2>

<p>So, without further adieu, here is the final list of phones I have purchased and where I got them from and how much they cost:</p>

<table class="reference">
  <thead>
    <tr>
      <th scope="col">OS</th>
      <th scope="col">Browser(s)</th>
      <th scope="col">Device</th>
      <th scope="col">Purchase Location</th>
      <th scope="col">Price (Rounded Up)</th>
    </tr>
  </thead>
  <tfoot>
    <tr class="grand-total">
      <th scope="row" colspan="4">Grand Total:</th>
      <td>$1811</td>
    </tr>
  </tfoot>
  <tbody>
    <tr>
      <td>iOS 3</td>
      <td>Webkit/528.18</td>
      <td><a href="http://support.apple.com/kb/SP570" rel="external">iPod Touch (3rd Gen.)</a></td>
      <td><a href="http://www.apple.com/ca/">apple.ca</a></td>
      <td>$191</td>
    </tr>
    <tr>
      <td>iOS 4</td>
      <td>Webkit/533.17</td>
      <td><a href="http://www.apple.com/iphone/iphone-3gs/specs.html" rel="external">iPhone 3GS</a></td>
      <td>(already own)</td>
      <td>—</td>
    </tr>
    <tr>
      <td>iOS 4</td>
      <td>Webkit/533.17</td>
      <td><a href="http://www.apple.com/ipad/specs/" rel="external">iPad</a></td>
      <td>(already own)</td>
      <td>—</td>
    </tr>
    <tr>
      <td>Android 1.6</td>
      <td>Webkit/528.5+</td>
      <td><a href="http://www.htc.com/us/products/t-mobile-mytouch-3g" rel="external">HTC myTouch (Magic)</a></td>
      <td><a href="http://www.ebay.ca" rel="external">ebay.ca</a></td>
      <td><strong>$163</strong></td>
    </tr>
    <tr>
      <td>Android 2.1</td>
      <td>Webkit/530.17, Firefox Mobile</td>
      <td><a href="http://www.sonyericsson.com/cws/corporate/products/phoneportfolio/specification/xperiax10" rel="external">Sony Ericsson Xperia X10</a></td>
      <td><a href="http://www.ebay.ca" rel="external">ebay.ca</a></td>
      <td><strong>$332</strong></td>
    </tr>
    <tr>
      <td>WebOS 1</td>
      <td>Webkit/532.2</td>
      <td><a href="http://www.palm.com/us/products/phones/pre/#tab2" rel="external">Palm Pre</a></td>
      <td><a href="http://ottawa.kijiji.ca" rel="external">ottawa.kijiji.ca</a></td>
      <td><strong>$120</strong></td>
    </tr>
    <tr>
      <td>BlackBerry OS 4</td>
      <td>BlackBerry Browser</td>
      <td><a href="http://us.blackberry.com/smartphones/blackberrycurve8300/curve_specifications.jsp" rel="external">BlackBerry Curve 8320</a></td>
      <td><a href="http://factorydirect.ca" rel="external">factorydirect.ca</a></td>
      <td><strong>$170</strong></td>
    </tr>
    <tr>
      <td>BlackBerry OS 5</td>
      <td>BlackBerry Browser</td>
      <td><a href="http://us.blackberry.com/smartphones/blackberrycurve8500/curve_specifications.jsp" rel="external">BlackBerry Curve 8520</a></td>
      <td><a href="http://factorydirect.ca" rel="external">factorydirect.ca</a></td>
      <td><strong>$283</strong></td>
    </tr>
    <tr>
      <td>Windows Mobile 6.5</td>
      <td>IE 6</td>
      <td><a href="http://www.gsmarena.com/htc_snap-2770.php" rel="external">HTC Snap</a></td>
      <td><a href="http://mobilicity.ca" rel="external">mobilicity.ca</a></td>
      <td><strong>$113</strong></td>
    </tr>
    <tr>
      <td>Symbian S40 6th</td>
      <td>Webkit/525</td>
      <td><a href="http://www.forum.nokia.com/Devices/Device_specifications/C3-00/" rel="external">Nokia C3-00</a></td>
      <td><a href="http://chatrwireless.ca" rel="external">chatrwireless.ca</a></td>
      <td><strong>$114</strong></td>
    </tr>
    <tr>
      <td>Symbian S60 3rd</td>
      <td>Webkit/413</td>
      <td><a href="http://www.forum.nokia.com/Devices/Device_specifications/N95-3_NAM/" rel="external">Nokia N95-3</a></td>
      <td><a href="http://ottawa.kijiji.ca" rel="external">ottawa.kijiji.ca</a></td>
      <td><strong>$125</strong></td>
    </tr>
    <tr>
      <td>Symbian S60 5th</td>
      <td>Webkit/420+</td>
      <td><a href="http://www.forum.nokia.com/Devices/Device_specifications/5800_XpressMusic/" rel="external">Nokia 5800 XpressMusic</a></td>
      <td><a href="http://ottawa.kijiji.ca" rel="external">ottawa.kijiji.ca</a></td>
      <td><strong>$200</strong></td>
    </tr>
  </tbody>
</table>

<h2 id="missingbrowsers">Missing Browsers</h2>

<p>You’ll Likely notice a few missing from the list. The first is the venerable mobile browser: <a href="http://www.opera.com/mobile/">Opera</a>. I didn’t go looking specifically for Opera because it can be installed on nearly any phone. I also didn’t go looking for a <a href="http://www.brewmp.com/">Brew MP</a> phone because Opera is the primary browser. Opera is already installed an a couple of the Nokia phones, I have it on my iPhone and I downloaded it to an Android phone.</p>

<p>I would like to support iPhone 4 with the double pixel ratio and am thinking of getting an iPod Touch to fill that gap. (Or maybe I’ll be bad just upgrade my iPhone.) Also, I’m unsure as to how much testing I should do on older versions of iOS.</p>

<p><a href="http://www.bada.com/">Samsung Bada</a> and <a href="http://maemo.nokia.com/">Nokia Maemo/MeeGo</a> only have one device each so there isn’t a huge market share. I’ll follow them and see where they go, but I’m not too worried since they are both Webkit-based and Gecko-based respectively.</p>

<p>Another Webkit-based browser, <a href="http://us.blackberry.com/apps-software/blackberry6/">BlackBerry OS 6</a>, definitely needs to be supported, but the devices are still new and expensive, so I thought I would wait a while. Similarly, <a href="http://www.microsoft.com/windowsphone/en-us/default.aspx">Windows Phone 7</a> needs to be supported but is very new and very expensive: also a waiter.</p>

<p>I thought about supporting older browsers, but decided it was a waste of my time since nobody in their right mind would surf the web on them anyways. I’m aware of the mobile Internet’s popularity in developing counties, but don’t really know what types of phones are being used and whether they are feature phones, smart phones, or anything about them except the <a href="http://gs.statcounter.com/#mobile_browser-ww-yearly-2008-2010">majority are Opera and Symbian</a>.</p>

<h2 id="unlockingdebrandingflashingotherfrustrations">Unlocking, Debranding, Flashing &amp; Other Frustrations</h2>

<p>I was lucky that all the phones I got in Canada worked over WiFi without a SIM card. Unfortunately the two phones I got from the United States did not.</p>

<p>The processes I describe below may seem simple, but it was my first time with all this stuff (and jargon) and it took me more than two frustrating hours, <em>full of swearing</em>, per phone, to get them functional.</p>

<h3 id="sonyericssonxperiax10">Sony Ericsson Xperia X10</h3>

<p>When I received the phone it was locked to AT&amp;T and completely locked out. I couldn’t get in to turn on WiFi, it would only allow emergency phone calls. I first tried <a href="http://unlocking.com">unlocking</a> the phone but couldn’t get a code. I then looked around and found out about debranding, which yielded the results I wanted.</p>

<p><dfn>Debranding</dfn> is the process of replacing the carrier’s custom firmware, AKA ‘flashing’, with the generic firmware supplied by the manufacturer. And it was the AT&amp;T firmware restricting the phone’s use without a connection to AT&amp;T’s network.</p>

<p>I basically had to <a href="http://forum.xda-developers.com/showthread.php?t=825201">download a debranding kit</a> and replace the firmware on the phone with the supplied generic one to remove the restrictions. It was a little scary—and very hacky—but worked.</p>

<h3 id="htcmytouchmagic">HTC myTouch (Magic)</h3>

<p>The HTC myTouch came a day after the major Xperia X10 frustrations but presented a different set of problems. When turning the phone on I was asked to sign in to my Google Account to set up the phone. I couldn’t skip the account sign in, the phone had no data plan, and there was no way to get WiFi turned on so I couldn’t get past this screen.</p>

<p>After doing some researching I discovered that I should have access to WiFi <em>and</em> should be able to skip the Google Account sign in, but T-Mobile’s firmware was restricting the phone and forcing a mobile data connection over their network.</p>

<p>Since I was successful at debranding the Xperia X10, I thought I would start there. Unfortunately I couldn’t find a straight forward process like I did for the X10, so I went back to unlocking.</p>

<p><dfn>Unlocking</dfn> is the process of allowing the phone to work on other networks. The myTouch was locked to T-Mobile, but I thought that if I unlocked it I could stick in my iPhone’s SIM and use it’s data connection to get past the Google Account screen.</p>

<p>After putting the $15 unlock code in and adding the <a href="http://androidforums.com/hero-support-troubleshooting/26867-setting-up-hero-fido.html">APN network connection for Fido</a>, I got past the account screen. After taking the SIM out, all’s good.</p>

<h2 id="nextsteps">Next Steps</h2>

<p>So, next I just need to figure out how to implement the mobile first approach on my web sites and how to support all the different platforms and screen sizes in a simple way. Off to the drawing board I go…</p>

<h2 id="helpfulresources">Helpful Resources</h2>

<ul>
<li><a href="http://www.forum.nokia.com/Devices/Device_specifications/?filter=all">Nokia Device Specifications</a></li>
<li><a href="http://www.google.com/phone/">Google Android Phones</a></li>
<li><a href="http://en.wikipedia.org/wiki/List_of_BlackBerry_products">BlackBerry Product List</a></li>
<li><a href="http://jquerymobile.com/gbs/">jQuery Mobile Graded Browser Support</a></li>
<li><a href="http://quirksmode.org/mobile/">QuirksMode Mobile</a></li>
<li><a href="http://quirksmode.org/mobile/browsers.html">QuirksMode Mobile Browsers</a></li>
<li><a href="http://www.webdirections.org/resources/john-resig-testing-mobile-javascript/">John Resig: Testing Mobile Javascript</a></li>
<li><a href="http://www.alistapart.com/articles/smartphone-browser-landscape/">A List Apart: Smartphone Browser Landscape</a></li>
</ul>

<hr />

<h2 id="updates">Updates</h2>

<ul>
<li><strong>Nov 30, 2010</strong>—Updated the total cost to include some customs fees and taxes.</li>
<li><strong>Dec 3, 2010</strong>—Added the section about unlocking and debranding. Added more customs fees to the total.</li>
<li><strong>Dec 15, 2010</strong>—Added some new links. Added the iPod Touch with iOS 3.</li>
<li><strong>Dec 20, 2010</strong>—Added Webkit versions.</li>
</ul>]]></content:encoded>
		</item>
		
		<item>
			<title>Open Data Ottawa</title>
			<link>http://thomasjbradley.ca/articles/open-data-ottawa</link>
			<pubDate>Mon, 19 Apr 2010 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/open-data-ottawa</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>My trials and tribulations in creating the Ottawa Park data set and a little overview of what my Open Data Ottawa app will be.</description>
			<content:encoded><![CDATA[<p><strong>My trials and tribulations in creating the Ottawa Park data set and a little overview of what my Open Data Ottawa app will be.</strong></p><p>Open Data is an important step for current governments and there has been a lot of discussion around the blog sphere. I won’t cover material that has already been documented elsewhere, but I do want to mention a local initiative, <a href="http://opendataottawa.ca">Open Data Ottawa</a>.</p>

<p>The City of Ottawa is very close to declaring the itself ‘open’ and to encourage the city departments to start opening up the data the Open Data Ottawa Hackfest was arranged.</p>

<p>It is <strong>Saturday, April 24th, 2010</strong> and <a href="http://guestlistapp.com/events/20361">tickets to the event are free, go reserve them</a>.</p>

<h2 id="afewopendataottawalinks">A Few Open Data Ottawa Links</h2>

<ul>
<li><a href="http://opendataottawa.ca/">Open Data Ottawa</a></li>
<li><a href="http://blog.opendataottawa.ca/">Open Data Ottawa Blog</a></li>
<li><a href="http://apps.opendataottawa.ca/">Open Data Ottawa App List</a></li>
<li><a href="http://guestlistapp.com/events/20361">Open Data Ottawa Registration</a></li>
<li><a href="http://twitter.com/opendataottawa">Open Data Ottawa on Twitter</a></li>
</ul>

<h2 id="ottawaparksdataset">Ottawa Parks Data Set</h2>

<p>For my contribution to the Open Data Ottawa Hackfest I am creating an application (more on that in a second) but first I needed a data set.</p>

<p>The city’s web site has a <a href="http://ottawa.ca/rec_culture/park_facility/parks/locations/index_en.html">list of all the parks</a> in Ottawa and their addresses. It also has a list of all the <a href="http://ottawa.ca/rec_culture/park_facility/parks/dogs/index_en.html">parks that allow/disallow dogs</a> split over five pages.</p>

<p>For my application I wanted to use that information, but there was no easily available place to get that information except through the city’s HTML tables on their web site (hence the need for open data).</p>

<p>I set out to extract all the information into a format that could be easily used for my application. The whole process probably took me about ten hours to complete. Here is a very general run-down of what I had to do to get the data in a decent, workable state.</p>

<h3 id="ottawaparksdatasetprocess">Ottawa Parks Data Set Process</h3>

<p>Originally I had wanted to do an automated screen scrape of the data, but after looking through it I felt that it was way too inconsistent to allow for anything totally automated.</p>

<p>So, I resorted to a slightly less elegant and slightly more manual method:</p>

<ol>
<li><p>I started with this list of dog parks: <a href="http://ottawa.ca/rec_culture/park_facility/parks/dogs/index_en.html">http://ottawa.ca/rec_culture/park_facility/parks/dogs/index_en.html</a>).</p></li>
<li><p>I opened each of the HTML tables in its print view and saved them to my desktop.</p></li>
<li><p>I then opened those HTML files in Microsoft Excel, which parsed them into a fairly usable spreadsheet.</p></li>
<li><p>Some of the tables had the addresses in the neighbouring cell and some had it in the cell below. So, I corrected all the addresses and put them in the neighbouring cell.</p></li>
<li><p>I then had a list of some of the city parks, but not all. So I browsed, printed and saved the master list: <a href="http://ottawa.ca/rec_culture/park_facility/parks/locations/index_en.html">http://ottawa.ca/rec_culture/park_facility/parks/locations/index_en.html</a> (Thankfully the master list had the addresses in the proper orientation.)</p></li>
<li><p>I then merged the two lists together in my Excel sheet and removed duplicates.</p></li>
<li><p>Now, I needed to parse the dog related information into something machine readable. I did that sort of manually by reading the dog information and using a series of cells, I entered 1 or 0 for each of the parks.</p>

<p>I also went through and augmented the information with the generalized info on the city’s web site like: ‘Rideau: Dogs on leash are permitted in parks’. In this case, I found all the Rideau parks and put that dogs were allowed, but required leashes.</p></li>
<li><p>At this point I had a huge list, but with a few major defects: almost everything was in ALL-CAPS (why would the city do that?) and I didn’t have any geo-location data for the parks, so they couldn’t be mapped easily.</p></li>
<li><p>To solve the ALL-CAPS, I copied the offending columns into the wonderful TextMate and ran the ‘Convert to Title Case’ action on them (its not perfect, but much better than ALL-CAPS). And then pasted them back into my spreadsheet.</p></li>
<li><p>Now for geo-location. I did some googling and found this batch geo-coding service, <a href="http://www.batchgeo.com/">http://www.batchgeo.com/</a>, that coincidentally allows you to past a spreadsheet of addresses and it will geo-code them all for you. Sweet!</p></li>
<li><p>An Excel spreadsheet is all jim-dandy but not very good for development purposes, so now I had to get my data out of Excel and into something I could use.</p>

<p>I originally decided I wanted it in a SQLite database, so I exported from Excel to CSV, which I could then import to SQLite. That may have sounded easy, but was far from it. Excel’s CSV output is far from optimal, so it took a bunch of validating and re-importing until the data was ready to go.</p></li>
<li><p>I am now about six—seven hours in and feeling pretty excited, so I packaged it up into a little repo with a couple Python scripts for extracting the SQLite data into other formats (CSV, XML and JSON) and released the data set into <a href="https://github.com/thomasjbradley/ottawaparks">GitHub</a>, tweeted it and went to bed.</p></li>
<li><p>The next morning I got an e-mail that my data was being used in an Open Data Ottawa app (great!) but at the same time there was an issue opened on GitHub with my data. Apparently a whack load of the latitudes/longitudes all pointed to the same location (what I realized later was city hall).</p>

<p>So off I go again trying to determine what was up. It turned out that the offending parks had addresses specified with intersections (and often many intersections). So I had to go through all those parks and correct their addresses and re—geo-code all those parks.</p></li>
<li><p>Upload to GitHub. Done. (Well done isn’t really final because I found an issue tonight with random extra quotes, but anyways.)</p></li>
</ol>

<p>So that, in a (very large) nut shell, is my adventure in producing the <a href="https://github.com/thomasjbradley/ottawaparks">Ottawa Parks data set</a>, now onto what I am going to use if for.</p>

<h2 id="ottawadogparkfinder">Ottawa Dog Park Finder</h2>

<p>The application idea was actually my wife’s from a couple years ago, you can actually still <a href="http://ottawadogblog.ca/2008/06/coming-soon-ottawa-dog-park-finder/">see the original announcement blog post</a>. We didn’t get very far on it because adding parks in was really time consuming and there weren&#8217;t any automated geo-location services at the time, it was all pretty manual.</p>

<p>So, I am restarting this application, but adding in a few new features.</p>

<p>The app is basically going to allow you to find parks in the city and whether they allow dogs on or off leash and other dog related information. It will be integrated with Google Maps and will allow you to enter locations and find parks closest to a specific location. And the app will hopefully allow users to vote on various aspects of the parks.</p>

<p>Wish me luck, because I only have a few days left.</p>]]></content:encoded>
		</item>
		
		<item>
			<title>Save View Source</title>
			<link>http://thomasjbradley.ca/articles/save-view-source</link>
			<pubDate>Fri, 08 Jan 2010 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/save-view-source</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>View source is an extremely important part of the web and one of the most important tools in my belt. But its existence is being threatened. Save View Source!</description>
			<content:encoded><![CDATA[<p><strong>View source is an extremely important part of the web and one of the most important tools in my belt. But its existence is being threatened. Save View Source!</strong></p><p>There are a few recent rumblings <a href="http://alex.dojotoolkit.org/2010/01/view-source-is-good-discuss/">on</a> <a href="http://ajaxian.com/archives/the-end-of-days-for-view-source">the</a> <a href="http://ajaxian.com/archives/view-source-how-important-was-it-is-it-and-will-it-be">web</a> that are starting to indicate that view source is on it’s way to extinction due to changes in the web including minification and the <a href="http://www.chromium.org/spdy">need for sp<ins>(ee)</ins>d</a>. We as web developers can’t let that happen!</p>

<h2 id="viewsourceandwebhistory">View Source and Web History</h2>

<p>View source has an extremely important history in web development. It has helped the proliferation of HTML through openness and simplicity. I dare to say that we may not be where we are without view source.</p>

<p>In my development, I rely on view source. It is one of the three things I need to do my job, the other two are a text editor and a browser. There isn’t an easier way to learn new things, debug your code or see if your dynamically generated code is written out properly than View Source.</p>

<p>As Alex Russell mentioned on an excellently written, <a href="http://alex.dojotoolkit.org/2010/01/view-source-is-good-discuss/">recent blog post</a>,</p>

<blockquote>
<p>The only required equipment is a text editor and a web browser, tools that are free and work together instantly. That is to say, there’s no waiting between when you save the file to disk and when you can view the results. It’s just a ctrl-r away. <cite><a href="http://alex.dojotoolkit.org/2010/01/view-source-is-good-discuss/">Alex Russell</a></cite></p>
</blockquote>

<p>If you haven’t read Alex’s post yet, you should, it’s a great read.</p>

<p>The web is not about compilers, it is about changing some text in a plain text file and opening it in a browser. The web encourages openness in learning because it is simply text.</p>

<h2 id="theopenweb">The Open Web</h2>

<p>The web is about being open. The standards the web is based upon aren’t public domain just because—they are public domain because it’s important that the web is available to everybody, equally. Net Neutrality and View Source are fighting similar battles, the battle to keep the web open.</p>

<p>How many times have you as a web developer used view source? At least once a day? View source is invaluable.</p>

<p>One of the things I constantly remind my web students is that view source is your friend. If you find a web site that does something you like, view source and then you can do it too.</p>

<p>In how many other professions can learning be done so openly and non-destructively. If you want to see how an electronic device is made you have to disassemble it. Imagine if you could view source on the internal mechanical workings your mobile phone.</p>

<p>Some people say that we don’t need view source any more because there are plenty of books and tutorials. I completely disagree. Books and tutorials are outdated, view source is real-time. (Isn’t that the way the web is going anyways?)</p>

<h2 id="webstandardsbrowsercompatibility">Web Standards &amp; Browser Compatibility</h2>

<p>Another major argument is, “if the web was compiled it would be less error prone and standards would be more easily followed.” I suppose that would be true. If the web was a compiled language we would get instant deal-breaking errors on any minor issue. Would that make the web easier to develop for? Yes. Would that make the web easier for non-technical users? No. Would that make the web less challenging and fun? Yes.</p>

<p>Even though all web developers complain about browser incompatibility, at the heart of it, isn’t that what draws us to the web. This idea of a vast, challenging <del>wild-west</del> frontier of platforms that we can target instantly with one text file. Being a web developer is about tackling the challenge of getting our few lines of text to work in as many browsers as possible.</p>

<p>Yes, browsers are incompatible and yes, they are inconsistent, but it is that challenge that should draw you to the profession. <strong>If you are not up to the browser inconsistency challenge then you have chosen the wrong profession.</strong></p>

<h2 id="minificationandobfuscation">Minification and Obfuscation</h2>

<p>Minification and obfuscation seem to be the two major reasons why view source is facing extinction. Minification is important to the web—we all love fast internet. Minification also doesn’t change your code other than compacting it down. With tools like Firebug and the Web Inspector the minification is undone. (Now if only view source would do that by itself.)</p>

<p>Obfuscation, on the other hand, is something I completely disagree with. <strong>The web is open!</strong> If your company feels they need to obfuscate their code on the web to hide how they did something, then they need to reconsider actually putting the content/application on the web. <strong>By hiding your code you are insulting the web.</strong></p>

<h3 id="viewsourceasawebservice">View Source as a Web Service</h3>

<p>Since minification is important for internet speed, maybe there should be some web service like standard where users/developers could request un-minified code for a resource.</p>

<h2 id="gagingwebdeveloperschops">Gaging Web Developers’ Chops</h2>

<p>Another reason I love view source is it’s an instant way for me to gage another web developer’s skills. If I find a web site that I like the first thing I do is view the source. The source of your web site says a lot about you as a developer. (Also I love to laugh at new sites that have table based layouts.)</p>

<p>To view another developer’s source is intimate and shows that you as the viewer care. If the developer also cares, it will be instantly recognisable in their source.</p>

<h2 id="saveviewsource">Save View Source</h2>

<p>View source needs to be saved! Go to <a href="http://saveviewsource.org">saveviewsource.org</a> to pledge your commitment to the Save View Source movement. View source needs you!</p>]]></content:encoded>
		</item>
		
		<item>
			<title>Mercurial or Git?</title>
			<link>http://thomasjbradley.ca/articles/mercurial-or-git</link>
			<pubDate>Thu, 10 Dec 2009 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/mercurial-or-git</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>Recently I made the decision. When SVN started to go wonky after my update to Snow Leopard, I knew I had to switch to a DVCS, but I didn’t know which to use.</description>
			<content:encoded><![CDATA[<p><strong>Recently I made the decision. When SVN started to go wonky after my update to Snow Leopard, I knew I had to switch to a DVCS, but I didn’t know which to use.</strong></p><p>Through my researching travels on the internet I quickly noticed that <em>all</em> the reviews other people wrote were old, usually a couple years old. The reviews also had one common theme through them all:</p>

<ul>
<li>Git is more complicated to use/learn and has more features;</li>
<li>and Mercurial is simpler to use/learn and has less features.</li>
</ul>

<p>But after much more researching and digging into the systems I realized this isn’t so much the case.</p>

<h2 id="featurecomparison">Feature Comparison</h2>

<p>I am not going to do a feature comparison here because there isn’t any reason to. <strong>Mercurial and Git have the same features.</strong> All the features are built in to Git, whereas Mercurial just requires extensions (often built in, but disabled by default).</p>

<p>My favourite comparative review is: <a href="http://importantshock.wordpress.com/2008/08/07/git-vs-mercurial/">Git is MacGyver and Mercurial is James Bond</a>.</p>

<h3 id="thegitindex">The Git Index</h3>

<p>People either love it or hate and it is one of the major points of contention. People choose Git because of it. People choose Mercurial because it doesn’t have it. And that reason is enough for many people.</p>

<p>But the truth is Mercurial does have an extension that adds a very similar idea: Mercurial Queues. Though the implementation is different, the same idea is there.</p>

<p>I didn’t even know if this was a reason I would choose Git or not. Yes, I could see the benefit of being able to commit just a few files at a time but also I could see it being a little annoying having to constantly specify the files I wanted to commit.</p>

<h3 id="localbranches">Local Branches</h3>

<p>Another major difference between the two was Git’s local branches. In Git branches are only local (by default). In Mercurial branches aren’t local—of course there is an extension for local branches in Mercurial.</p>

<p>This wasn’t a major issue for me because I would be using the DVCS primarily for my own client projects, on my own development server. So it didn’t really matter whether the branches are local or not.</p>

<h3 id="builtinpython">Built in Python</h3>

<p>I have been having a bit of a PHP crisis lately. I am outgrowing PHP and Python is looking pretty awesome. It is kinda weird, but I feel like Python is a perfect fit for the way I work, though I only know a little yet. So the fact that Mercurial is built in Python and can be imported and used natively in Python apps was a really compelling feature.</p>

<h3 id="commandlinefu">Command Line Fu</h3>

<p>Git is seen as requiring a lot of command line fu and Mercurial is always proud of its simple, intuitive command line interface. Though Git has gotten better/simpler in the more recent versions, there apparently are a few nagging, weird things. Since I am not super amazing at the command line yet (but trying hard), I could see this as a plus for Mercurial. One review I read mentioned that Git is like Linux (wow, that’s a creative comparison): requires a lot of configuration and Mercurial is like Mac: slick and simple to use, with hidden power.</p>

<h2 id="thepopularkidintown">The Popular Kid in Town</h2>

<p>Git is the popular kid in town right now. And people <em>love</em> it! Since Git’s popularity is so great, finding help for it should be easy because so many people are talking about/using it. I have always hated the popular kid and that makes me respect Mercurial a little more as the underdog.</p>

<h2 id="github">GitHub</h2>

<p><a href="https://github.com/">GitHub</a> is awesome! And the guys behind it <a href="https://github.com/blog/">really care</a>. GitHub is a major plus for Git. Yes, <a href="http://bitbucket.com/">BitBucket</a> exists, but lacks many of the social aspects that make GitHub what it is. Then I found <a href="http://hg-git.github.com/">Hg-Git</a>, a Mercurial plugin to allow Mercurial direct integration with Git (and GitHub)—made by the guys at GitHub. Hg-Git makes me respect the service GitHub offers even more. (Will you marry me GitHub? I love you.)</p>

<h3 id="thegithubcommunity">The GitHub Community</h3>

<p>Git has a massive community and recently I read a couple tweets that may, or may not have, influenced my decision.</p>

<p>Positive:</p>

<blockquote>
<p>“I’m loving the influx of new contributors to jQuery core since moving to Github.” —&nbsp;<cite><a href="http://twitter.com/jeresig/status/6387795184">@jereisig</a></cite></p>
</blockquote>

<p>And negative:</p>

<blockquote>
<p>“Is github now a Single Point of Failure for the whole OSS ecosystem? I love it, but worry a bit.” —&nbsp;<cite><a href="http://twitter.com/timbray/status/6411879609">@timbray</a></cite></p>
</blockquote>

<h2 id="sowhatdidichoose">So, What Did I Choose?</h2>

<p>Well, it was a stressful decision and took me about two weeks after all my research to actually make the decision.</p>

<p><strong>And my decision was… Mercurial.</strong></p>

<p>I chose Mercurial for a couple reasons, <em>I think</em>. First I decided that since my command line abilities aren’t as strong as I would like, Mercurial seemed like the simpler choice. I also thought Git may be too complicated and have too many features for my first foray into the command line version control eco-system (previously, with SVN, I used a GUI). Since Mercurial has all the same features, I liked the idea that they were hidden until I was comfortable with the basic features and could unlock them as I needed them. A few other things that influenced my decision were Hg-Git, my support of underdogs and the whole Python thing.</p>

<p>After using if for almost a week I am, so far, happy with my decision. But I admit I have already run into a situation where Git Index would have been very useful.</p>

<hr />

<h2 id="updates">Updates</h2>

<p>Two years after this post, I now switch back and forth between Git and Mercurial. I use both GitHub and BitBucket (BitBucket now supports Git). I’ve even got more proficient with the command line, but I still find Mercurial more user friendly.</p>

<p><strong><a href="http://gitvsmercurial.com/">I think this site sums the discussion up nicely.</a></strong></p>]]></content:encoded>
		</item>
		
		<item>
			<title>First Lab Project: Signature Pad</title>
			<link>http://thomasjbradley.ca/articles/first-lab-project-signature-pad</link>
			<pubDate>Thu, 03 Dec 2009 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/first-lab-project-signature-pad</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>Signature Pad is a jQuery plugin for assisting in the creation of an HTML5 canvas based signature pad. Records the drawn signature in JSON for later regeneration.</description>
			<content:encoded><![CDATA[<p><strong>Signature Pad is a jQuery plugin for assisting in the creation of an HTML5 canvas based signature pad. Records the drawn signature in JSON for later regeneration.</strong></p><p>Signature Pad is the first official project posted to my <a href="/lab/">lab section</a> (and there are two more projects in the queue). Getting something posted on labs has been a long time coming, but it’s finally here.</p>

<h2 id="alittlehistory">A Little History</h2>

<p>Signature Pad started out using Flash and ExternalInterface instead of HTML5 Canvas. It worked, but wasn’t easily configured and—of course—<em>relied</em> on Flash. The signature bits were a little slow on my Mac and saving out the signature as an image wasn’t as reliable as I hoped.</p>

<p>I wanted to make something faster, simpler and more reliable and preferably standards based. So I set out to duplicate the functionality in Javascript/Canvas.</p>

<p>I was surprised at how quickly it came together in canvas, but not without a few IE related hick-ups. After making the first prototype I decided that it would be a great <a href="http://plugins.jquery.com/">jQuery plugin</a>.</p>

<h2 id="makingajqueryplugin">Making a jQuery Plugin</h2>

<p>Making a jQuery plugin was a rewarding experience and I found it to be fairly simple. It really helped me understand a few things about Javascript that I had never used before.</p>

<p>Here are a couple resources that helped:</p>

<ul>
<li><a href="http://docs.jquery.com/Plugins/Authoring">jQuery Plugin Authoring Docs</a></li>
<li><a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern">Learning jQuery: A Plugin Development Pattern</a></li>
<li><a href="http://snook.ca/archives/javascript/jquery_plugin">Snook: Developing a jQuery Plugin</a></li>
</ul>

<p>I also found it really helpful to look at other jQuery plugins and see how they did things.</p>

<h2 id="themajorhick-ups">The Major Hick-ups</h2>

<p>There were a few major hick-ups, related to IE, while developing the plugin.</p>

<p>The first plagued IE7 and IE8 and was related to initially drawing the grey signature line on the canvas. I had it working for a while and then it stopped and I had a long drawn battle to figure out why.</p>

<p>Through my debugging I discovered that only on the first call to the <code>drawSigLine()</code> method, the line wasn’t drawn, but every subsequent time it worked.</p>

<p>I don’t fully remember how I came to the solution, but the solution was just to not draw the line immediately on page load. Instead I created a timeout of 50 milliseconds that would then draw the line when it fired. Problem solved.</p>

<p>The second major issue plagued IE8 only and was related to <a href="http://code.google.com/p/explorercanvas/">Explorer Canvas</a>. In IE8 strict mode, I couldn’t draw on the canvas. By couldn’t draw, I mean I could draw, it just wouldn’t display.</p>

<p>Through some online digging I found that excanvas sets <code>overflow: hidden</code> on the VML div that it creates. This prompted me to add a <em>wonderful</em> hack to my code that checks for the div with <code>overflow: hidden</code> and set it’s overflow to visible.</p>

<h2 id="documentationandexamples">Documentation and Examples</h2>

<p>The lab section has complete examples, documentation and tutorials on the Signature Pad.</p>

<ul>
<li><a href="/lab/signature-pad/">Documentation &amp; Tutorials</a></li>
<li><a href="/lab/signature-pad/accept">Demo of Accepting a Signature</a></li>
<li><a href="/lab/signature-pad/regenerate">Demo of Regenerating a Signature</a></li>
</ul>]]></content:encoded>
		</item>
		
		<item>
			<title>Mental Visualizations: Colour Association</title>
			<link>http://thomasjbradley.ca/articles/mental-visualizations-colour-association</link>
			<pubDate>Fri, 20 Nov 2009 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/mental-visualizations-colour-association</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>One common trick to remember things is association. To continue my series in mental visualization I am going to discuss my mind’s automatic, subconscious association of colours and numbers.</description>
			<content:encoded><![CDATA[<p><strong>One common trick to remember things is association. To continue my series in mental visualization I am going to discuss my mind’s automatic, subconscious association of colours and numbers.</strong></p><p>The human mind is powerful at remembering things and one of the ways it helps us remember is through association. Sometimes that association is conscious, like rhyming or song, but many times it is subconscious. One of the strongest associations in my mind is between colours and numbers.</p>

<h2 id="interchangeablecoloursnumbers">Interchangeable Colours &amp; Numbers</h2>

<p>Numbers <strong>are</strong> colours. When I see numbers in my head I <em>always</em> picture them in a specific colour. If I remove the English symbol of a number and leave just the colour I see the same thing. This subconscious memory trick is especially helpful for remembering a long series of numbers like a phone number or bank account. In my mind’s eye, I see a series of colours and from that the numbers are assigned.</p>

<h2 id="whatdoesitlooklike">What Does it Look Like?</h2>

<p>I am sure you are all interested in what the colours are, so have a gander.
<ul class="mental-nums clearfix">
 <li style="color:#f1f1f1;opacity:0.6">0</li>
 <li style="color:#fff;">1</li>
 <li style="color:#cec38e;">2</li>
 <li style="color:#ffe400;">3</li>
 <li style="color:#ffae00;">4</li>
 <li style="color:#2c438c;">5</li>
 <li style="color:#2a7526;">6</li>
 <li style="color:#acacac;">7</li>
 <li style="color:#6a4f3c;">8</li>
 <li style="color:#515150;">9</li>
</ul></p>

<p>This is in no way a perfect representation of the colours. It is really difficult to describe the colours in physical form. When I start to think about what the colours are, I almost have troubles seeing the colours.</p>

<p>The only number that isn’t easily described in a static graphic is zero. Zero is actually transparent, like glass. This, I am sure, has some association to the fact that zero represents nothing, therefore my colour <em>is</em> nothing. I should also mention that one is pure white.</p>

<p>Also, like my <a href="/articles/mental-visualizations-the-year-loop/">Year Loop</a>, the numbers in my mind are always in a vast black void.</p>

<h2 id="sohowdoesitwork">So, How Does it Work?</h2>

<p>Well, it only works in my mind when I think about numbers. If I am looking at numbers on a page, I see them in the colour presented, but when I think about them, they are presented in their associated colour. If the writing on the page is black and it contains an eight, in my mind I will see the black writing with a brown eight in the middle.</p>

<p>It happens so fast, but it seems as though the numbers are stored in my brain as a colour, when I want to remember numbers, I recall a series of colours and my brain instantly translates those into numbers.</p>

<h2 id="thestrongestassociation:time">The Strongest Association: Time</h2>

<p>Though all numbers are colour associated in my mind, time is somehow associated more strongly. I don’t really know how to explain it, maybe the time colours are brighter, as if they are generating their own light, where other numbers are just reflecting the ambient light. Either way, time is especially strongly linked to colour.</p>

<ul class="mental-nums clearfix">
    <li style="color:#cec38e;">2</li>
    <li>:</li>
    <li style="color:#2c438c;">5</li>
    <li style="color:#6a4f3c;">8</li>
</ul>

<p>When thinking about a time in my mind the colour association is so strong it almost hides the English numeric symbol. But not in a way that blurs the numbers, more that the colours are so bright (like looking into the sun) that you can’t see the shape, just the colour.</p>

<p>When I look at a representation of time, on a clock for instance, unlike the other numbers, the time digits are kind of more visible as their mentally associated colour. I am aware of the colour the time is being presented in, but at the same time aware of the colour association.</p>

<h2 id="whatdoesitsayaboutme">What Does it Say About Me?</h2>

<p>Do I associate to colours because I have an inclination towards design? Or is it just a simpler, smaller representation to be stored in my brain? Instead of storing the complex lines and shapes of a number, my brain simply stores a colour.</p>

<p>It would be great is someone could explain this working of my mind to me, but until that point I am just going to write it off as another <del>quirk</del> <ins>complexity</ins> of the human mind.</p>

<h2 id="relatedposts">Related Posts</h2>

<ul>
<li><a href="/articles/mental-visualizations-the-year-loop/">Mental Visualizations: The Year Loop</a></li>
</ul>

<hr />

<h2 id="updates">Updates</h2>

<p>National Geographic recently published an article titled <a href="http://news.nationalgeographic.com/news/2011/11/111123-evolution-brain-synesthesia-taste-colors-sounds-creative-science/">Why Does Evolution Allow Some People to Taste Words?</a> that mentions synesthesia. Synesthesia sounds very similar to the colour association I’ve described above.</p>]]></content:encoded>
		</item>
		
		<item>
			<title>Mental Visualizations: The Year Loop</title>
			<link>http://thomasjbradley.ca/articles/mental-visualizations-the-year-loop</link>
			<pubDate>Thu, 19 Nov 2009 00:00:00 -0500</pubDate>
			<guid isPermaLink="true">http://thomasjbradley.ca/articles/mental-visualizations-the-year-loop</guid>
			<dc:creator>Thomas J Bradley</dc:creator>
			<description>Do you ever think about how you think about the calendar year? Meta-thinking? We all have our little quirks about how we see and visualize things in our mind. The following is how the year passes in my mind.</description>
			<content:encoded><![CDATA[<p><strong>Do you ever think about how you think about the calendar year? Meta-thinking? We all have our little quirks about how we see and visualize things in our mind. The following is how the year passes in my mind.</strong></p><p>The year is represented as a two-dimensional loop that rotates and scales in three-dimensions with a black void as the backdrop. The months start with January at the top left then proceeds counter-clockwise ending with July at the bottom left. August then connects to July on the bottom right and it’s a straight shot to December, which connects back to January. Have a look at the graphic on the right to get an understanding of how the system is designed.</p>

<h2 id="threedimensionsofcalendar">Three Dimensions of Calendar</h2>

<p>The graphic presented on the right is a static version of the what the calendar year would look, if it was zoomed-out. In my mind though, it is never presented zoomed out. It moves around and repositions itself depending on the context—and context is very important. As an example, lets say I am at the tail end of December and am looking forward in time to January. The year loop would go into a perspective mode that presents January top centre and December below. As time passes in January the calendar flies around the January curve towards February. And now I can see February and the next few months ahead of me.</p>

<h2 id="picturesareworthathousandwords">Pictures Are Worth a Thousand Words</h2>

<p>Especially when describing something that only I can only—and ever will—see. So I have created a very basic mock-up of the year loop in a three-dimensional Flash movie.</p>

<figure>
<img src="http://images2.thomasjbradley.ca/articles/year-loop/year-loop.png" alt="" id="" /></figure>



<div>
    <figure style="text-align:center; background-color:#000;">
        <embed src="http://images2.thomasjbradley.ca/articles/year-loop/year-loop.swf" type="application/x-shockwave-flash" allowscriptaccess="always" width="700" height="400">
    </figure>
</div>

<p>The representation is very basic and only really presents one context: looking ahead in month view. The year loop in my mind is much more dynamic and flexible. Instead of feeling like a solid plastic mass (like in Flash) it is more of a flexible fabric object. The months bend, stretch and adjust based on time and view. Also, in my mental visualization all the days of each month are represented on the loop, not just the weeks.</p>

<h2 id="contextisimportant">Context is Important</h2>

<p>As I mentioned earlier, the year loop is very context based. In the Flash example we can see only the months. But if I wanted to look at the last week of February the year loop would spin around and put February into a view similar to a standard wall calendar. The view would still have quite a bit of perspective and I can see March starting at the bottom and January fading away at the top. This view also lets me zoom in to specific weeks and days.</p>

<p>Another aspect of the context is when I am looking forward from December. The January that I see is next year. Similarly, when I look back from January I see the previous year’s December.</p>

<h2 id="thepassageoftime">The Passage of Time</h2>

<p>My mental understanding of the passage time is also represented in my year loop. You can see that February to July are actually <em>shorter</em> months compared to the autumn months. This is from my internal clock that always feels those months speed by faster than the fall months.</p>

<h2 id="calendardirectionalityandholidays">Calendar Directionality and Holidays</h2>

<p>Another interesting aspect is the directionality of the calendar. From January to July, I have the passed months behind me, as though I am looking forward to something. The summer possibly? But when I hit August the calendar turns and I start looking backwards, trying to hide the future behind my field of view. It’s my belief that my mental calendar faces towards the closest holiday or time-off period: in January I am facing the summer, in August I am looking back on the summer and trying to avoid September. Then in October, the calendar starts to turn again, this time looking forward to the winter holidays and the new year.</p>

<h2 id="interestinglimitations">Interesting Limitations</h2>

<p>One interesting quirk is that months always end on the far right of their box, regardless of whether they end on a Saturday or not. And similarly months always start on the far left of their box, whether they start on a Sunday or not. My mental model does not generally recognize mid-week month starts/ends. Instead, when I need to understand, the graphic is replaced by a picture of a calendar, usually the one hanging on my wall showing the mid-week month switch. (This year it is my Chuck Norris Facts calendar.) This somehow is related to my constant forgetfulness of months starting in mid-week.</p>

<h2 id="whatdoesitallmeanbasil">What Does it All Mean, (Basil)?</h2>

<p>Well, I can’t really say. I am sure it says something about my personality, abilities and learned behaviours from a psychological perspective—but what, I don’t know. When talking to <a href="http://lizkerrison.ca">Liz</a> about this post, she reminded me of her mental visualization of the calendar year. It is similar than mine, but also different. Her’s travels clockwise and is more circular from January to August. Then in September it is a straight line up to December where it reconnects with January.</p>

<p>It is interesting to me to think about how my mind thinks about things and equally as interesting to see how other people think about things. Or even if they think about how they think about things. Also, it would be interesting to see the similarities and differences between everybody’s mental visualizations. Meta thinking, think about it. (Don’t you love that cheesy final sentence!)</p>

<p><strong>Tomorrow, this post will be followed up with another post in the series: <a href="/articles/mental-visualizations-colour-association/">Colour Association</a>.</strong></p>]]></content:encoded>
		</item>
		
	</channel>
</rss>

