<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.jordanelver.co.uk/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom">
 
  <title>Jordan Elver</title>
  <subtitle>The personal website of Jordan Elver</subtitle>
  
  <link href="http://jordanelver.co.uk/" />
  <updated>2011-08-03T19:56:48+01:00</updated>
  <author>
    <name>Jordan Elver</name>
    <email>me@jordanelver.co.uk</email>
  </author>
  <id>http://jordanelver.co.uk/</id>
  
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.jordanelver.co.uk/jordanelver" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="jordanelver" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>It's the little things</title>
    <link href="/articles/2011/07/30/its-the-little-things/" />
    <id>tag:jordanelver.co.uk,2011-07-30:1312037783</id>
    <updated>2011-07-30T15:56:23+01:00</updated>
    <content type="html">&lt;p&gt;I've been thinking about the &lt;a href="http://littlebigdetails.com/"&gt;little things&lt;/a&gt; that can be changed to make a web page easier to use. Seemingly small changes can add up to have a big impact on the way people will interact with the page.&lt;/p&gt;

&lt;p&gt;On one particular site, I have a pretty standard widget used to select the amount of products to show per page. I'm sure you've seen something similar to that of below on many other websites.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/dropdown.gif" alt="Example of a dropdown list used to select the amount of products to show on the page" /&gt;&lt;/p&gt;

&lt;p&gt;The way this is currently implemented, it takes &lt;strong&gt;three&lt;/strong&gt; clicks to complete the intended operation. This could be reduced to &lt;strong&gt;two&lt;/strong&gt; clicks by adding some JavaScript to trigger the page change (and removing the button), but there is a problem with this method: The options at &lt;strong&gt;not all visible&lt;/strong&gt; at once. You have to click to see what the options are.&lt;/p&gt;

&lt;h4&gt;Rethinking the implementation&lt;/h4&gt;

&lt;p&gt;I decided to change the way this was implemented, moving to a horizontal list of links.&lt;/p&gt;

&lt;p&gt;&lt;img src="/images/list.gif" alt="Example of a list used to select the amount of products to show on the page" /&gt;&lt;/p&gt;

&lt;p&gt;The advantages of this approach are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see all options at once. Please, &lt;a href="http://www.amazon.co.uk/Dont-Make-Me-Think-Usability/dp/0321344758"&gt;don't make me think&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;It's only a &lt;strong&gt;single&lt;/strong&gt; click to select an option.&lt;/li&gt;
&lt;li&gt;It's better for accessibility because you don't have to fiddle with a dropdown (and who wants to?).&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I think this is a fairly good example of how changing small things, perhaps even those that seem inconsequential, can contribute to improving the overall experience of the page, and delight the user.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Rails Footnotes problem</title>
    <link href="/articles/2011/07/24/rails-footnotes-problem/" />
    <id>tag:jordanelver.co.uk,2011-07-24:1311504023</id>
    <updated>2011-07-24T11:40:23+01:00</updated>
    <content type="html">&lt;p&gt;I recently had a head-scratching time trying to figure out why code that integrates with a 3rd party payment processor had suddenly stopped working. The code in question simply returns a text only response to the 3rd party, who then read, parse and act on it. Within my Rails controller:&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;render &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;text&lt;/span&gt; &lt;span class="SourceBase"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Status=OK,Detail=Some details here&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I found the culprit by going through my git log to see what had changed recently. Turns out it was the recent addition of Rails Footnotes causing the problem. &lt;a href="http://rubydoc.info/gems/rails-footnotes/3.7.4/frames"&gt;Rails Footnotes&lt;/a&gt; is an awesome gem that adds various information about your app to the bottom of every page including clickable links to controllers, views and partials. Clicking these links opens the file in your text editor of choice.&lt;/p&gt;

&lt;p&gt;Rails Footnotes was appending its debugging HTML (as designed) to my text-only response, breaking the payment processors parsing. After an &lt;a href="http://railstips.org/blog/archives/2010/10/14/stop-googling/"&gt;inspection of the source&lt;/a&gt; I noticed that Footnotes are only output if the content type includes "html", such as "text/html".&lt;/p&gt;

&lt;h4&gt;The fix&lt;/h4&gt;

&lt;p&gt;In my case the whole controller could (and probably should) be returned as "text/plain". I hooked up a &lt;code&gt;before_filter&lt;/code&gt; to add the &lt;code&gt;Content-Type&lt;/code&gt; header to the response and that fixed it.&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="SourceBase"&gt;&lt;span class="Keyword"&gt;class&lt;/span&gt; &lt;span class="TypeName"&gt;NotificationController&lt;span class="ClassInheritance"&gt; &lt;span class="ClassInheritance"&gt;&amp;lt;&lt;/span&gt; ApplicationController&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class="Comment"&gt;  &lt;span class="Comment"&gt;#&lt;/span&gt; Set the content type to text/plain so footnotes don't show&lt;/span&gt;
  before_filter &lt;span class="Constant"&gt;&lt;span class="Constant"&gt;:&lt;/span&gt;set_content_type&lt;/span&gt;

  &lt;span class="SourceBase"&gt;&lt;span class="Keyword"&gt;def&lt;/span&gt; &lt;span class="FunctionName"&gt;set_content_type&lt;/span&gt;&lt;/span&gt;
    headers&lt;span class="SourceBase"&gt;[&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;Content-Type&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;]&lt;/span&gt; &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;text/plain&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;
  &lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;span class="Keyword"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;For versions of Rails Footnotes greater than 3.7.0 (which is Rails 3 only) you can actually configure if Footnotes are added to the page using an initializer (or similar). Unfortunately, I'm still using Rails 2 on this project so I currently can't take advantage of that.&lt;/p&gt;

&lt;h4&gt;In conclusion&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://rubydoc.info/gems/rails-footnotes/3.7.4/frames"&gt;Rails Footnotes&lt;/a&gt; is a must-have, you really should check it out.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Automatically attaching to a tmux session via SSH</title>
    <link href="/articles/2010/11/27/automatically-attaching-to-a-tmux-session-via-ssh/" />
    <id>tag:jordanelver.co.uk,2010-11-27:1290822503</id>
    <updated>2010-11-27T01:48:23+00:00</updated>
    <content type="html">&lt;p&gt;I've been using &lt;a href="http://tmux.sourceforge.net/"&gt;tmux&lt;/a&gt; as a &lt;a href="http://www.gnu.org/software/screen/"&gt;screen&lt;/a&gt; replacement for a while now. I find it easier to use and configure than screen. I tend to leave a tmux session running on servers that I administer so that everything is just as it was when I last connected. It's very handy.&lt;/p&gt;

&lt;p&gt;To make this even more convenient, I wanted to be able to automatically attach to a running tmux session when connecting to servers using &lt;a href="http://en.wikipedia.org/wiki/Secure_Shell"&gt;SSH&lt;/a&gt;. The SSH client already comes with the ability to run a command when connecting. It works like this:&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;ssh &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;hostname&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;command&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Unfortunately, this didn't work when I tried attaching to a tmux session.&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;ssh &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;hostname&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt; tmux a
not a terminal
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;After a bit of Googling, it turns out that you need to supply the &lt;code&gt;-t&lt;/code&gt; option to the &lt;code&gt;ssh&lt;/code&gt; command. The ssh man page describes the option as such:&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;-t Force pseudo-tty allocation. This can be used to execute
   arbitrary screen-based programs on a remote machine, 
   which can be very useful, e.g., when implementing menu
   services.
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If we do that, we're in business:&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;ssh &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;hostname&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt; -t tmux a
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;To make the command even shorter, I've been adding bash aliases to my &lt;code&gt;~/.bash_profile&lt;/code&gt; for each server I connect to, like so:&lt;/p&gt;

&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;alias servername=&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;ssh servername -t tmux a&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, I can just type &lt;code&gt;servername&lt;/code&gt; and get a SSH connection to servername with tmux automatically attached. Issuing a &lt;code&gt;&amp;lt;ctrl&amp;gt; + b + d&lt;/code&gt; will detach the tmux session and disconnect the SSH connection.&lt;/p&gt;

&lt;p&gt;Command line magic!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>How to upgrade Phusion Passenger for nginx</title>
    <link href="/articles/2009/11/27/how-to-upgrade-phusion-passenger-for-nginx/" />
    <id>tag:jordanelver.co.uk,2009-11-27:1259340420</id>
    <updated>2009-11-27T16:47:00+00:00</updated>
    <content type="html">&lt;p&gt;I keep forgetting the procedure to upgrade Passenger and nginx, so thought I&amp;#8217;d
note them down here in case anyone finds it useful. These instructions assume
that:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;You already have &lt;a href="http://www.modrails.com/"&gt;Phusion Passenger&lt;/a&gt; installed and configured for &lt;a href="http://nginx.net/"&gt;nginx&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;re using &lt;a href="http://www.rubyenterpriseedition.com/"&gt;Ruby Enterprise Edition&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Upgrade&lt;/h4&gt;
&lt;p&gt;Download the latest nginx source and uncompress to a temporary directory.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; cd &lt;span class="Keyword"&gt;~&lt;/span&gt;/sources
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; wget http://sysoev.ru/nginx/nginx-0.7.64.tar.gz
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; tar xzvf nginx-0.7.64.tar.gz
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Install the latest Passenger gem&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; sudo /opt/ruby-enterprise-1.8.6-20090520/bin/gem install passenger
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Run the Passenger installer&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; sudo /opt/ruby-enterprise-1.8.6-20090520/bin/passenger-install-nginx-module
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Follow the onscreen instructions, choose option 2 to use your own sources.
Specify the location of the nginx sources when prompted.&lt;/p&gt;
&lt;p&gt;If you want to use any other optional nginx modules, enable them when prompted.
I want to use the SSL and Status modules, so I enable them like this:&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; --with-http_ssl_module --with-http_stub_status_module
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The full configure line will look something like this:&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; ./configure --prefix=&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;/opt/nginx&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; --with-pcre=&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;/tmp/pcre-7.8&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; --add-module=&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;/opt/ruby-enterprise-1.8.6-20090520/lib/ruby/gems/1.8/gems/passenger-2.2.5/ext/nginx&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt; --with-http_ssl_module --with-http_stub_status_module
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After the installer has finished, the new version will be installed in 
&lt;code&gt;/opt/nginx&lt;/code&gt; and the old version will be renamed to &lt;code&gt;nginx.old&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Configure&lt;/h4&gt;
&lt;p&gt;Update the &lt;code&gt;nginx.conf&lt;/code&gt; with the correct paths, you should only need to change
the path to the &lt;code&gt;passenger_root&lt;/code&gt; directive.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; http &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="SourceBase"&gt;    ...&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="SourceBase"&gt;    passenger_root /opt/ruby-enterprise-1.8.6-20090520/lib/ruby/gems/1.8/gems/passenger-2.2.5&lt;span class="Keyword"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; &lt;span class="SourceBase"&gt;    ...&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;h4&gt;Restart&lt;/h4&gt;
&lt;p&gt;I like to do a config file syntax check before I restart nginx, just in case
of typos and the like.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; sudo /opt/nginx/sbin/nginx -t -c /opt/nginx/conf/nginx.conf
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If the check is successful, restart nginx.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; sudo /etc/init.d/nginx restart
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You should now be running the latest version of Passenger and nginx.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Google Analytics Ecommerce Tracking</title>
    <link href="/articles/2008/08/07/google-analytics-ecommerce-tracking/" />
    <id>tag:jordanelver.co.uk,2008-08-07:1218120401</id>
    <updated>2008-08-07T15:46:41+01:00</updated>
    <content type="html">&lt;p&gt;So you&amp;#8217;ve installed &lt;a href="http://www.google.com/analytics"&gt;Google Analytics&lt;/a&gt;, the superb 
free web analytics software and it&amp;#8217;s telling you all sorts of things about your site,
most of which you don&amp;#8217;t even understand. You&amp;#8217;re learning what a &lt;a href="http://en.wikipedia.org/wiki/Bounce_Rate"&gt;Bounce Rate&lt;/a&gt;
is and realising how powerful this thing really is.&lt;/p&gt;
&lt;p&gt;Well, it gets even better. I&amp;#8217;ve recently discovered its&amp;#8217; Ecommerce tracking feature.
It allows you to capture Ecommerce related statistics alongside your normal web related
statistics. Once you have it correctly setup for your site you can see how much
money you&amp;#8217;ve taken in sales, how many transactions have taken place, how many 
products have been purchased, and your Ecommerce conversion rate. Very nice.&lt;/p&gt;
&lt;h4&gt;Make it so&lt;/h4&gt;
&lt;p&gt;In order to activate Ecommerce tracking, you need to firstly turn on the feature 
within Google Analytics, and secondly add some extra JavaScript code to your receipt or thanks page.&lt;/p&gt;
&lt;p&gt;To turn on the feature, go to the Profile Settings for your site, click Edit (top right)
and under E-Commerce Website, select &amp;#8220;Yes, an E-Commerce Site&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the extra code you need to add to the receipt page straight from &lt;a href="http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&amp;amp;answer=55528"&gt;Google&amp;#8217;s help page&lt;/a&gt;.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;script type&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;text/javascript&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; &lt;span class="SourceBase"&gt;var&lt;/span&gt; gaJsHost &lt;span class="Keyword"&gt;=&lt;/span&gt; &lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;https:&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;==&lt;/span&gt; &lt;span class="SourceBase"&gt;document&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="SourceBase"&gt;location&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="SourceBase"&gt;protocol&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt; ? &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;https://ssl.&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; : &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;http://www.&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="SourceBase"&gt;document&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="SupportFunction"&gt;write&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SupportFunction"&gt;unescape&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;%3Cscript src='&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;+&lt;/span&gt; gaJsHost &lt;span class="Keyword"&gt;+&lt;/span&gt; &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;/script&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;script type&lt;span class="Keyword"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;text/javascript&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt; &lt;span class="SourceBase"&gt;var&lt;/span&gt; pageTracker &lt;span class="Keyword"&gt;=&lt;/span&gt; _gat&lt;span class="SourceBase"&gt;.&lt;/span&gt;_getTracker&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;UA-XXXXX-1&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; pageTracker&lt;span class="SourceBase"&gt;.&lt;/span&gt;_trackPageview&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt; pageTracker&lt;span class="SourceBase"&gt;.&lt;/span&gt;_addTrans&lt;span class="SourceBase"&gt;(&lt;/span&gt;
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;1234&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                     &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Order ID&lt;/span&gt;
&lt;span class="line-numbers"&gt;  12 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Mountain View&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                            &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Affiliation&lt;/span&gt;
&lt;span class="line-numbers"&gt;  13 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;11.99&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                    &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Total&lt;/span&gt;
&lt;span class="line-numbers"&gt;  14 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;1.29&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                     &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Tax&lt;/span&gt;
&lt;span class="line-numbers"&gt;  15 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;5&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                        &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Shipping&lt;/span&gt;
&lt;span class="line-numbers"&gt;  16 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;San Jose&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                 &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; City&lt;/span&gt;
&lt;span class="line-numbers"&gt;  17 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;California&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                               &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; State&lt;/span&gt;
&lt;span class="line-numbers"&gt;  18 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;USA&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;                                       &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Country&lt;/span&gt;
&lt;span class="line-numbers"&gt;  19 &lt;/span&gt; &lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  20 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  21 &lt;/span&gt; pageTracker&lt;span class="SourceBase"&gt;.&lt;/span&gt;_addItem&lt;span class="SourceBase"&gt;(&lt;/span&gt;
&lt;span class="line-numbers"&gt;  22 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;1234&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                     &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Order ID&lt;/span&gt;
&lt;span class="line-numbers"&gt;  23 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;DD44&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                     &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; SKU&lt;/span&gt;
&lt;span class="line-numbers"&gt;  24 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;T-Shirt&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                  &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Product Name&lt;/span&gt;
&lt;span class="line-numbers"&gt;  25 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Green Medium&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                             &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Category&lt;/span&gt;
&lt;span class="line-numbers"&gt;  26 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;11.99&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;,                                    &lt;/span&gt;&lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Price&lt;/span&gt;
&lt;span class="line-numbers"&gt;  27 &lt;/span&gt;   &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;1&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;                                         &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; Quantity&lt;/span&gt;
&lt;span class="line-numbers"&gt;  28 &lt;/span&gt; &lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  29 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  30 &lt;/span&gt; pageTracker&lt;span class="SourceBase"&gt;.&lt;/span&gt;_trackTrans&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;  31 &lt;/span&gt; &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;/script&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;#8217;re already using Analytics, the first few lines will be familier to you. They&amp;#8217;re
just the standard page tracking calls. The bits we&amp;#8217;re interested in are the 
&lt;code&gt;pageTacker._addTrans()&lt;/code&gt;, &lt;code&gt;pageTracker._addItem()&lt;/code&gt; and &lt;code&gt;pageTracker._trackTrans()&lt;/code&gt; methods.
You&amp;#8217;ll need to fill in the relevant details, and more importantly repeat the &lt;code&gt;_addItem&lt;/code&gt; 
call for each item within the order. The method for doing this will obviously differ depending
on your server side choices, but for Rails I&amp;#8217;ve got something similar to this.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;@&lt;/span&gt;order&lt;/span&gt;&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;items&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;each&lt;/span&gt;&lt;/span&gt; &lt;span class="Keyword"&gt;do &lt;/span&gt;&lt;span class="SourceBase"&gt;|&lt;/span&gt;&lt;span class="SourceBase"&gt;item&lt;/span&gt;&lt;span class="SourceBase"&gt;|&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;   pageTracker._addItem(
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;     &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;@&lt;/span&gt;order&lt;/span&gt;&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;order_id&lt;/span&gt;&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;,                     // Order ID
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;     &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;@&lt;/span&gt;order&lt;/span&gt;&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;sku&lt;/span&gt;&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;,                          // SKU
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;     &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%=&lt;/span&gt; item&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;product&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;name&lt;/span&gt;&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;,                   // Product Name
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;     &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%=&lt;/span&gt; item&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;product&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;category&lt;/span&gt;&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;,               // Category
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt;     &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%=&lt;/span&gt; item&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;unit_price&lt;/span&gt;&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;,                     // Price
&lt;span class="line-numbers"&gt;   9 &lt;/span&gt;     &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%=&lt;/span&gt; item&lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="FunctionName"&gt;qauntity&lt;/span&gt;&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;                        // Quantity
&lt;span class="line-numbers"&gt;  10 &lt;/span&gt;   );
&lt;span class="line-numbers"&gt;  11 &lt;/span&gt; 
&lt;span class="line-numbers"&gt;  12 &lt;/span&gt; &lt;span class="SourceBase"&gt;&lt;span class="SourceBase"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="Keyword"&gt;end&lt;/span&gt; &lt;span class="SourceBase"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You should now start to get E-Commerce stats showing up under the Ecommerce section of
Google Analytics.&lt;/p&gt;
&lt;h4&gt;References&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.google.com/support/googleanalytics/bin/answer.py?hl=en&amp;amp;answer=55528"&gt;Google Analytics Help&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.epikone.com/blog/2008/07/02/google-analytics-e-commerce-tracking-pt-4-tacking-lead-gen-forms/"&gt;Analytics Talk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  
  <entry>
    <title>jQuery Event Delegation</title>
    <link href="/articles/2009/06/03/jquery-event-delegation/" />
    <id>tag:jordanelver.co.uk,2009-06-03:1244069280</id>
    <updated>2009-06-03T23:48:00+01:00</updated>
    <content type="html">&lt;p&gt;Recently, I&amp;#8217;ve been working on adding some extra features to a shopping cart page using &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt;. The idea is that you select your country from a dropdown and an &lt;acronym title="Asynchronous JavaScript and XML"&gt;AJAX&lt;/acronym&gt; request is performed, which updates a list of radio buttons on the page. If you select one of these radio buttons, it triggers another &lt;acronym title="Asynchronous JavaScript and XML"&gt;AJAX&lt;/acronym&gt; request, which updates the postage prices for the given items in the basket.&lt;/p&gt;
&lt;p&gt;Each of the radio buttons has an event like this bound to it.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;$&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;#options input&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="SupportFunction"&gt;click&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;function&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt; &lt;span class="SourceBase"&gt;{&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; lookup postage prices via ajax&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt; &lt;span class="SourceBase"&gt;}&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This triggers the &lt;acronym title="Asynchronous JavaScript and XML"&gt;AJAX&lt;/acronym&gt; request which looks up the postage prices from the database. It works fine with the default set of radio buttons that are present on the page when it loads. The problem comes when new radio buttons are added to the page via &lt;acronym title="Asynchronous JavaScript and XML"&gt;AJAX&lt;/acronym&gt;. When a new radio button is added to the list, it doesn&amp;#8217;t automatically have a click event (like the one above) bound to it like the existing items do. The events are not automatically carried across to the new item you&amp;#8217;ve added.&lt;/p&gt;
&lt;p&gt;We can get around this problem by re-binding the events each time a new radio button is added to the page. But this can be messy and there is a much cleaner way of solving the problem.&lt;/p&gt;
&lt;h4&gt;Event delegation to the rescue&lt;/h4&gt;
&lt;p&gt;This is where event delegation comes in. Event delegation takes advantage of the fact that browsers &amp;#8220;bubble&amp;#8221; events up the &lt;acronym title="Document Object Model"&gt;DOM&lt;/acronym&gt; when they are triggered on a page. For example, given the &lt;acronym title="HyperText Markup Language"&gt;HTML&lt;/acronym&gt; below, when clicking the radio button the browser will generate a click event which will &amp;#8220;bubble&amp;#8221; upwards so that first the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element receives the event, followed by the &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;, then the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;&lt;/span&gt;&lt;span class="TagName"&gt;div&lt;/span&gt; &lt;span class="TextBase"&gt;&lt;span class="TagAttribute"&gt;id&lt;/span&gt;&lt;span class="TextBase"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="String"&gt;options&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;&lt;/span&gt;&lt;span class="TagName"&gt;p&lt;/span&gt;&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;     &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;&lt;/span&gt;&lt;span class="TagName"&gt;input&lt;/span&gt; &lt;span class="TagAttribute"&gt;type&lt;/span&gt;=&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;radio&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="TagAttribute"&gt;value&lt;/span&gt;=&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;1&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="TextBase"&gt;&lt;span class="TagAttribute"&gt;id&lt;/span&gt;&lt;span class="TextBase"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="String"&gt;postage_method_1&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;   &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="TagName"&gt;p&lt;/span&gt;&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt;   &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;&lt;/span&gt;&lt;span class="TagName"&gt;p&lt;/span&gt;&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   6 &lt;/span&gt;     &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;&lt;/span&gt;&lt;span class="TagName"&gt;input&lt;/span&gt; &lt;span class="TagAttribute"&gt;type&lt;/span&gt;=&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;radio&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="TagAttribute"&gt;value&lt;/span&gt;=&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;2&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="TextBase"&gt;&lt;span class="TagAttribute"&gt;id&lt;/span&gt;&lt;span class="TextBase"&gt;=&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;span class="String"&gt;postage_method_2&lt;/span&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; /&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   7 &lt;/span&gt;   &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="TagName"&gt;p&lt;/span&gt;&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   8 &lt;/span&gt; &lt;span class="TextBase"&gt;&lt;span class="TextBase"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="TagName"&gt;div&lt;/span&gt;&lt;span class="TextBase"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We can take advantage of this &amp;#8220;event bubbling&amp;#8221;. Instead of binding the event to each individual &lt;code&gt;input&lt;/code&gt;, we&amp;#8217;ll bind it to a parent element instead and let the click events from the inputs bubble up to the parent element. In this case, the div called options.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; &lt;span class="Keyword"&gt;$&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;#options&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="SupportFunction"&gt;click&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;function&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;event&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt; &lt;span class="SourceBase"&gt;{&lt;/span&gt;
&lt;span class="line-numbers"&gt;   2 &lt;/span&gt;   &lt;span class="Keyword"&gt;if&lt;/span&gt; &lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="Keyword"&gt;$&lt;/span&gt;&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="SourceBase"&gt;event&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;&lt;span class="SourceBase"&gt;target&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;.&lt;/span&gt;is&lt;span class="SourceBase"&gt;(&lt;/span&gt;&lt;span class="String"&gt;&lt;span class="String"&gt;'&lt;/span&gt;input&lt;span class="String"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;{&lt;/span&gt;
&lt;span class="line-numbers"&gt;   3 &lt;/span&gt;     &lt;span class="Comment"&gt;&lt;span class="Comment"&gt;//&lt;/span&gt; do ajax request&lt;/span&gt;
&lt;span class="line-numbers"&gt;   4 &lt;/span&gt;   &lt;span class="SourceBase"&gt;}&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;span class="line-numbers"&gt;   5 &lt;/span&gt; &lt;span class="SourceBase"&gt;}&lt;/span&gt;&lt;span class="SourceBase"&gt;)&lt;/span&gt;&lt;span class="SourceBase"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now, each time we add an additional input to the page, it will automatically respond to the same event as the rest of the inputs.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s worth noting that this event will get triggered whenever any element under the &lt;code&gt;#options&lt;/code&gt; div is clicked, so inside the event we check that the target of the event was an &lt;code&gt;input&lt;/code&gt; element. This will restrict the code inside the event so that it only executes when it&amp;#8217;s an &lt;code&gt;input&lt;/code&gt; that&amp;#8217;s been clicked.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Event delegation greatly improves the readability of the code. It sounds scary, but really isn&amp;#8217;t. It also has the added benefit of speeding up the processing of the page because you&amp;#8217;re not spending time looping through many DOM elements (which takes time) in order to add your event handlers.&lt;/p&gt;
&lt;p&gt;Check out the references below for a much better explanation of how event delegation and binding of event handlers work.&lt;/p&gt;
&lt;h4&gt;References&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://icant.co.uk/sandbox/eventdelegation/"&gt;Event Delegation versus Event Handling&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://lab.distilldesign.com/event-delegation/"&gt;Event Delegation with jQuery&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery"&gt;Event Delegation Made Easy&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Learning jQuery &amp;#8211; Working with Events, &lt;a href="http://www.learningjquery.com/2008/03/working-with-events-part-1"&gt;part 1&lt;/a&gt;, and &lt;a href="http://www.learningjquery.com/2008/05/working-with-events-part-2"&gt;part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  
  <entry>
    <title>htop - a prettier top</title>
    <link href="/articles/2008/12/31/htop-a-prettier-top/" />
    <id>tag:jordanelver.co.uk,2008-12-31:1230690300</id>
    <updated>2008-12-31T02:25:00+00:00</updated>
    <content type="html">&lt;p&gt;You use &lt;a href="http://en.wikipedia.org/wiki/Top_%28Unix%29"&gt;top&lt;/a&gt; right? No? Well, that&amp;#8217;s probably because top is not the friendliest
program in the world. Yes, it gets the job done, but it could be prettier.
As I was using top more and more for monitoring my VPS, I looked for something a bit nicer.&lt;/p&gt;
&lt;p&gt;This is where &lt;a href="http://htop.sourceforge.net/"&gt;htop&lt;/a&gt; comes in. It&amp;#8217;s top, but with colours, progress bars, and a
process tree view. Much better. Try it, you might like it.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/htop.jpg" /&gt;&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Changing Recent Commits with Git</title>
    <link href="/articles/2008/12/16/changing-recent-commits-with-git/" />
    <id>tag:jordanelver.co.uk,2008-12-16:1229457625</id>
    <updated>2008-12-16T20:00:25+00:00</updated>
    <content type="html">&lt;p&gt;Have you ever committed to your repo and realised you&amp;#8217;ve done something a bit silly? I just did that. I moved to a new machine and forgot to setup my &lt;code&gt;.gitconfig&lt;/code&gt; with the correct username and email, so when I committed, the commit had the wrong user against it. Not a big problem, but it just looks a bit&amp;#8230;well, untidy.&lt;/p&gt;
&lt;p&gt;Fear not. Git is all-powerful and allows you to change your mistake even
though you&amp;#8217;ve already committed it. Thanks to Tekkub on the 
&lt;a href="http://groups.google.com/group/github"&gt;GitHub Google Group&lt;/a&gt; for
the nudge in the right direction.&lt;/p&gt;
&lt;h4&gt;How does I dos it?&lt;/h4&gt;
&lt;p&gt;Like this.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; git reset --soft HEAD^
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This will reset your working copy to the state before you committed and remove
the commit so you can make changes to your working copy (if needed) and re-commit.&lt;/p&gt;
&lt;p&gt;Re-commit the changes.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; git commit -m &lt;span class="String"&gt;&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;Changed something&lt;span class="String"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;#8217;ve already pushed to &lt;a href="http://www.github.com"&gt;GitHub&lt;/a&gt; or another external repo, you can re-push, but you&amp;#8217;ll need 
to add &lt;code&gt;--force&lt;/code&gt; because we have removed a commit locally and Git doesn&amp;#8217;t like that.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; git push origin --force
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;#8217;m not sure whether this would be a good idea if someone else has cloned your repo, but
I&amp;#8217;m ok because I am the only person who pushes to this one.&lt;/p&gt;
&lt;p&gt;Git is great, but powerful, so be careful. I&amp;#8217;m sure it would be easy to completely
trash your repo with the wrong series of commands.&lt;/p&gt;</content>
  </entry>
  
  <entry>
    <title>Git Patching Flexibility</title>
    <link href="/articles/2008/08/04/git-patching-flexibility/" />
    <id>tag:jordanelver.co.uk,2008-08-04:1217860406</id>
    <updated>2008-08-04T15:33:26+01:00</updated>
    <content type="html">&lt;p&gt;I don&amp;#8217;t know about you, but when I&amp;#8217;m coding I&amp;#8217;ll often need to make a change 
that&amp;#8217;s unrelated to the current feature or bug I am working on. I&amp;#8217;ll notice a
spelling mistake, a typo, or some other small code change. You don&amp;#8217;t want to 
commit the unrelated change as part of your overall commit because, well, 
it&amp;#8217;s unrelated. It should be its own commit with its own commit message.
This will make it much easier to read the commit log and cuts down on confusion.
People won&amp;#8217;t have to ask &amp;#8220;Why did they change that? It has nothing to do with the change&amp;#8221;&lt;/p&gt;
&lt;p&gt;When I used Subversion, you had to remove the unrelated change, commit, then 
add it back in and commit again. Maybe there was a nicer way, but I didn&amp;#8217;t 
know it. Git is much nicer.&lt;/p&gt;
&lt;p&gt;When you stage a file ready for committing, Git allows you to only stage a 
certain part or parts of the file, which it calls hunks.&lt;/p&gt;
&lt;p&gt;So, run:&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; git add --patch &lt;span class="Keyword"&gt;&amp;lt;&lt;/span&gt;filename&lt;span class="Keyword"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Git will show you a diff of the first difference that it wants to stage and
will ask if you&amp;#8217;d like to stage the current hunk, like this:&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; Stage this hunk [y/n/a/d/s/?]? 
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The options in this example are:&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="TextBase"&gt;y - stage this hunk&lt;/span&gt;
&lt;span class="TextBase"&gt;n - do not stage this hunk&lt;/span&gt;
&lt;span class="TextBase"&gt;a - stage this and all the remaining hunks in the file&lt;/span&gt;
&lt;span class="TextBase"&gt;d - do not stage this hunk nor any of the remaining hunks in the file&lt;/span&gt;
&lt;span class="TextBase"&gt;s - split the current hunk into smaller hunks&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Choose what you&amp;#8217;d like to do with the current hunk. Git will continue to go through the 
rest of the hunks in the file, asking you what to do with each one.&lt;/p&gt;
&lt;p&gt;When you&amp;#8217;ve decided which hunks should be staged, commit as normal and only
those changes will form part of the commit. You can then add the rest of 
your changes and commit again.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s the flexibility that&amp;#8217;s great. It works with you, not against you.&lt;/p&gt;
&lt;p&gt;For a much more in depth look at the capabilities of &lt;code&gt;git add --patch&lt;/code&gt;, see
the following article.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://tomayko.com/writings/the-thing-about-git"&gt;The Thing About Git&lt;/a&gt; by &lt;a href="http://tomayko.com/"&gt;Ryan Tomayko&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  
  <entry>
    <title>How to generate / request an SSL certificate</title>
    <link href="/articles/2008/07/24/how-to-generate-request-an-ssl-certificate/" />
    <id>tag:jordanelver.co.uk,2008-07-24:1216906084</id>
    <updated>2008-07-24T14:28:04+01:00</updated>
    <content type="html">&lt;p&gt;Generating an SSL certificate can be confusing if you&amp;#8217;ve never done it
before. Actually, it&amp;#8217;s confusing if you have done it before. Hopefully this 
should remind me how to do it in the future!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PLEASE NOTE:&lt;/strong&gt; I am no expert on SSL, but this does the job for me.&lt;/p&gt;
&lt;p&gt;I recently had to do this after the &lt;a href="http://www.ubuntu.com/usn/usn-612-1"&gt;Debian security vulnerability&lt;/a&gt;
affected one of my SSL certificates.&lt;/p&gt;
&lt;p&gt;I currently get my SSL cerficiates through &lt;a href="http://www.namecheap.com"&gt;NameCheap&lt;/a&gt; for $10.
They are re-sellers of RapidSSL and GeoTrust certificates. Mine is a RapidSSL.&lt;/p&gt;
&lt;h4&gt;Generate a private key and Certificate Signing Request&lt;/h4&gt;
&lt;p&gt;We need to generate an OpenSSL keypair and a &lt;a href="http://en.wikipedia.org/wiki/Certificate_signing_request" title="CSR"&gt;Certificate Signing Request&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The keypair consists of two cryptographic keys. A public and private. The public
key is included with the CSR along with other applicant information such as name,
company, etc. The private key is used to sign the CSR request.&lt;/p&gt;
&lt;p&gt;A CSR is what you send to your chosen Certificate Authority (CA) to request that
they supply you with an SSL certificate. It includes your identifying information
and the public key for your server/site.&lt;/p&gt;
&lt;p&gt;Generate it like this.&lt;/p&gt;
&lt;div class="UltraViolet"&gt;
&lt;pre class="all_hallows_eve"&gt;&lt;span class="line-numbers"&gt;   1 &lt;/span&gt; openssl req -new -newkey rsa:1024 -nodes -keyout example.key -out example.csr
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You&amp;#8217;ll be prompted to enter information such as Common Name, Organisation, Country etc.&lt;/p&gt;
&lt;p&gt;It should be fairly straight forward, but your CA will let you know if you&amp;#8217;ve done it wrong, I&amp;#8217;m sure.&lt;/p&gt;
&lt;p&gt;This will create &lt;code&gt;example.key&lt;/code&gt; (the private key) and &lt;code&gt;example.csr&lt;/code&gt; (the CSR).&lt;/p&gt;
&lt;h4&gt;Requesting your certificate&lt;/h4&gt;
&lt;p&gt;This part should be easy. Normally your CA will have a form on their website which allows you
to paste in your CSR. This obviously varies from company to company. Once you have given them
your CSR, they will first ask you for money, and then generate your CRT file. Yay!&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m only scratching the surface of SSL here. OpenSSL has a massive amount of options. There is much to learn.&lt;/p&gt;
&lt;h4&gt;References&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="https://help.ubuntu.com/community/OpenSSL"&gt;More information on OpenSSL commands&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  
</feed>

