<?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.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en" xml:base="http://nefariousdesigns.co.uk/wp-atom.php">
	<title type="text">Nefarious Designs</title>
	<subtitle type="text">Nefarious Designs is the web development agency and blog of Tim Huegdon, a web developer with over 5 years experience in the industry.</subtitle>

	<updated>2009-05-21T21:43:47Z</updated>
	<generator uri="http://wordpress.org/" version="2.7.1">WordPress</generator>

	<link rel="alternate" type="text/html" href="http://nefariousdesigns.co.uk" />
	<id>http://nefariousdesigns.co.uk/feed/atom/</id>
	

			<logo>http://nefariousdesigns.co.uk/favicon.ico</logo><link rel="self" href="http://feeds.feedburner.com/nefariousdesigns" type="application/atom+xml" /><entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[Unit Testing: The Basics]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/WNDmFQ48frI/" />
		<id>http://nefariousdesigns.co.uk/?p=187</id>
		<updated>2009-05-21T21:43:47Z</updated>
		<published>2009-05-03T11:36:52Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="Python" /><category scheme="http://nefariousdesigns.co.uk" term="Testing" /><category scheme="http://nefariousdesigns.co.uk" term="Tools" /><category scheme="http://nefariousdesigns.co.uk" term="Tutorials" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[As a web development manager, it&#8217;s part of my job to be involved in defining best practices for my team. This means defining a set of standard practices that will benefit the whole team throughout the entire development process. A good example of one such best practice would be code testing.
Testing, for web developers, is [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2009/05/unit-testing-the-basics/"><![CDATA[<p>As a web development manager, it&#8217;s part of my job to be involved in defining best practices for my team. This means defining a set of standard practices that will benefit the whole team throughout the entire development process. A good example of one such best practice would be code testing.</p>
<p>Testing, for web developers, is usually a fairly disorganised affair. Most of the time, we test &#8220;on the job&#8221;, i.e., we code something and then we run it; if it breaks, we fix it. In fact, often, the thought of actually structuring our testing process can seem somewhat of an over complication. This is certainly not the case.</p>
<p>The benefits of a structured testing process are legion, as any software engineer will attest. At the very least, it provides confidence in our code &#8212; something which can only be of incredible benefit when code is shared across a wider team. At its best, the tests we write can influence the way we develop the code being tested; and save effort, time, and money.</p>
<p>In this post I&#8217;m going to look at &#8220;unit testing&#8221;, and how it can be of benefit to web developers in general.</p>
<p><span id="more-187"></span></p>
<h2>What <em>is</em> unit testing?</h2>
<p>Unit testing is the process of validating and verifying the individual &#8220;units&#8221; of code in a system. A unit is the smallest testable part of a system or application. In the majority of cases within web development, these units are usually individual functions or methods of our object-oriented back-end and front-end code.</p>
<p>At this point, it&#8217;s probably worth noting that unit testing is really only applicable to functional code, such as PHP, JavaScript, Python, Perl, Ruby etc., because it breaks down into units nicely. Testing mark-up and CSS is a slightly different process and one that I may look at in a future blog post.</p>
<h2>A note on language</h2>
<p>The concept of unit testing is entirely language agnostic, therefore the examples in the following tutorials can be ported to PHP, Perl, Ruby, JavaScript, or any other functional or object-oriented language you are using.</p>
<p>I&#8217;ll use Python as the language for all examples in this post as it&#8217;s my current weapon of choice (and the interactive interpreter is very handy for trying out ideas); if you&#8217;ve never seen Python syntax, don&#8217;t worry, it&#8217;s easily understandable (if you want more information, take a look at <a href="http://docs.python.org/tutorial/">the Python tutorial</a>).</p>
<h2>Writing a simple test</h2>
<p>To begin with, let&#8217;s imagine we have a function for calculating the area of a rectangle:</p>
<pre><code>def get_area_of_rect( width, height ):
    return width * height</code></pre>
<p>Let&#8217;s paste this function into the interactive interpreter, so that we can play with it:</p>
<pre><samp>>>> <kbd>def get_area_of_rect( width, height ):</kbd>
... <kbd>    return width * height</kbd>
...
>>> </samp></pre>
<p>Now if we call it, we&#8217;ll receive the area of our rectangle like so:</p>
<pre><samp>>>> <kbd>get_area_of_rect( 2, 3 )</kbd>
6
>>></samp></pre>
<p>Now if we wanted to test this function, we could call it with a some defined parameters and test the output against our expectations:</p>
<pre><code>def test_get_area_of_rect():
    width = 2
    height = 3
    expected_result = 6

    result = get_area_of_rect( width, height )

    if result == expected_result:
        print "Test passed: Received expected result!"</code></pre>
<p>Now if we run our test, we should see the following:</p>
<pre><samp>>>> <kbd>test_get_area_of_rect()</kbd>
Test passed: Received expected result!
>>></samp></pre>
<p>Brilliant; our code passed the test because the <em>expected</em> result was the same as the <em>actual</em> result &#8212; however, that&#8217;s actually not very useful to us. It&#8217;s far more important that our tests can trap <em>failing</em> code than code that works.</p>
<p>Imagine our <code>get_area_of_rect</code> function had been updated as follows:</p>
<pre><code>def get_area_of_rect( width, height ):
    return width / height</code></pre>
<p>Anyone with rudimentary maths skills can tell that this will no longer return the correct area of a rectangle. In fact, if we rerun our test, we&#8217;ll get no output:</p>
<pre><samp>>>> <kbd>test_get_area_of_rect()</kbd>
>>></samp></pre>
<p>A fat lot of good <em>that</em> is. If our code is failing for some reason, we want to know about it. After all, that&#8217;s the whole reason for testing it.</p>
<p>Let&#8217;s update the <code>if</code> statement in our <code>test_get_area_of_rect</code> function:</p>
<pre><code>if not result == expected_result:
    raise AssertionError
else:
    print "Test passed: Received expected result!"</code></pre>
<p>In fact, we could probably dump the <code>else</code> clause since it&#8217;s of little real importance except for logging purposes:</p>
<pre><code>if not result == expected_result:
    raise AssertionError</code></pre>
<p>That&#8217;s nicer, but Python provides us a shortcut to this <code>if not &hellip; raise AssertionError</code> syntax with the <code>assert</code> statement:</p>
<pre><code>assert result == expected_result</code></pre>
<p>With that in mind, the <code>test_get_area_of_rect</code> function should now look like this:</p>
<pre><code>def test_get_area_of_rect():
    width           = 2
    height          = 3
    expected_result = 6

    result = get_area_of_rect( width, height )

    assert result == expected_result</code></pre>
<p>If we run our test again, we should receive more constructive output, considering our <code>get_area_of_rect</code> function is still dividing:</p>
<pre><samp>>>> <kbd>test_get_area_of_rect()</kbd>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in test_get_area_of_rect
AssertionError
>>></samp></pre>
<p>We now have a decent automated test, but we&#8217;re only checking a single expected result. If, for instance, we passed in a width of 1 and a height of 1, both multiplication and division would return the same result: 1. This means that we should pass multiple sets of width and height parameters and test against their expected results. Since these parameters will be constant, let&#8217;s define them as tuples and loop through them, testing each in turn:</p>
<pre><code>def test_get_area_of_rect():
    known_values = ( ( 0, 0, 0 ),
                     ( 1, 1, 1 ),
                     ( 2, 2, 4 ),
                     ( 2, 3, 6 ),
                     ( 3, 0, 0 ) )

    for width, height, expected_result in known_values:
        result = get_area_of_rect( width, height )
        assert result == expected_result</code></pre>
<p>As you can see, we&#8217;re now passing several sets of parameters. Each set of parameters is valid, and as such, we should expect a successful outcome from our <code>get_area_of_rect()</code> call.</p>
<p>Now if we run our test, we should get something like the following:</p>
<pre><samp>>>> <kbd>test_get_area_of_rect()</kbd>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in test_get_area_of_rect
  File "<stdin>", line 2, in get_area_of_rect
ZeroDivisionError: integer division or modulo by zero
>>></samp></pre>
<p>Ah ha! By passing multiple sets of parameters we&#8217;ve uncovered more significant information regarding the <code>AssertionError</code> that was raised earlier; we have a division by zero error on line 2 of <code>get_area_of_rect</code>. This has supplied us with all the information we need to fix our error, so let&#8217;s take a look at that function again:</p>
<pre><code>def get_area_of_rect( width, height ):  # Line 1
    return width / height               # Line 2</code></pre>
<p>Change the division back to multiplication, like so:</p>
<pre><code>def get_area_of_rect( width, height ):  # Line 1
    return width * height               # Line 2</code></pre>
<p>And then rerun our test:</p>
<pre><samp>>>> <kbd>test_get_area_of_rect()</kbd>
>>> </samp></pre>
<p>We get no output at all because the test passed successfully. As the old proverb goes, &#8220;no news is good news&#8221;.</p>
<p>Now if we add to our original code in the future, we&#8217;ll still be able to run this testing code to see what has been affected. What&#8217;s more, we can add to it by writing <em>more</em> tests, should the complexity grow. In fact, creating an extensive suite of tests is generally the aim of unit testing, but to do so, it&#8217;s a good idea to utilise a testing framework, which I&#8217;ll look at in the next post of this series.</p>
<h2>Summary</h2>
<p>Writing tests for code enables more efficient debugging, faster bug fixing, and an overall confidence in the quality of your code. Furthermore, the rest of your team (or whomsoever you&#8217;re sharing said code with) will equally have confidence thanks to the tests included.</p>
<p>In brief, here&#8217;s what we&#8217;ve learnt about unit testing:</p>
<ul>
<li>It&#8217;s most important that your tests catch failure, not success.</li>
<li>Test the smallest amount of code, or &#8220;unit&#8221;, possible each time.</li>
<li>Test as many different parameters, inputs, and outputs as possible.</li>
<li>Run the tests often.</li>
</ul>
<h2>The next post</h2>
<p>In the next post, I&#8217;ll be expanding on unit testing by looking at test frameworks, test architecture, code coverage, and other more advanced techniques that can improve your testing environment.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2009/05/unit-testing-the-basics/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2009/05/unit-testing-the-basics/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2009/05/unit-testing-the-basics/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[Housekeeping]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/7SfTHVhMbng/" />
		<id>http://nefariousdesigns.co.uk/?p=183</id>
		<updated>2009-04-13T10:14:55Z</updated>
		<published>2009-04-13T10:14:55Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="Site" /><category scheme="http://nefariousdesigns.co.uk" term="Syndication" /><category scheme="http://nefariousdesigns.co.uk" term="Tools" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[I&#8217;ve just completed some quick housekeeping on the site &#8212; mostly on my feed.
I noticed last night that Google had acquired Feedburner, and that I needed to port my feed over to my Google account. At the same time, I swapped the feed to use Atom instead of RSS. Having completed that, I decided to [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2009/04/housekeeping/"><![CDATA[<p>I&#8217;ve just completed some quick housekeeping on the site &#8212; mostly on my feed.</p>
<p>I noticed last night that <a href="http://www.feedburner.com/google">Google had acquired Feedburner</a>, and that I needed to port my feed over to my Google account. At the same time, I swapped the feed to use Atom instead of RSS. Having completed that, I decided to address a problem with my feed that&#8217;s been bugging me for some time:</p>
<p>My feed has always published only an excerpt of each post, instead of the full post. This is because I use the &#8220;more&#8221; break functionality in Wordpress for the introduction snippets in the bespoke home page theme files, instead of writing an entirely separate excerpt. On previous versions of Wordpress, this also limited the RSS feed regardless of whether you had specifically chosen the &#8220;display full article&#8221; option in the syndication settings. I&#8217;ve had a couple of complaints about this, since most developers seem to prefer reading articles in their feed readers &#8212; and so do I, for that matter.</p>
<p>Last time I needed to fix this problem, I had a hell of a time trying to find the offending code in the horrific Wordpress PHP. Thankfully, since then, the bug has been fixed so all I needed to do was update Wordpress. Having completed that update, my feed should now be working as intended originally.</p>
<p>The next step, it seems, will be getting off Wordpress to something home-grown.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2009/04/housekeeping/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2009/04/housekeeping/feed/atom/" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2009/04/housekeeping/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[A better OS X development environment]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/b3kdjz5EWJ8/" />
		<id>http://nefariousdesigns.co.uk/archive/2009/04/a-better-os-x-development-environment/</id>
		<updated>2009-04-13T09:52:48Z</updated>
		<published>2009-04-12T21:41:44Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Apache" /><category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="Django" /><category scheme="http://nefariousdesigns.co.uk" term="Linux" /><category scheme="http://nefariousdesigns.co.uk" term="Mac OS X" /><category scheme="http://nefariousdesigns.co.uk" term="MySQL" /><category scheme="http://nefariousdesigns.co.uk" term="PHP" /><category scheme="http://nefariousdesigns.co.uk" term="Python" /><category scheme="http://nefariousdesigns.co.uk" term="Server" /><category scheme="http://nefariousdesigns.co.uk" term="Tutorials" /><category scheme="http://nefariousdesigns.co.uk" term="UNIX" /><category scheme="http://nefariousdesigns.co.uk" term="Virtualisation" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[When I first began developing using a Mac I made use of the bundled versions of Apache and PHP that were included in OS X Tiger. This meant I only needed to install MySQL to be able to develop fairly complex websites.
However, as my requirements evolved, I discovered that recompiling PHP to include support for [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2009/04/a-better-os-x-development-environment/"><![CDATA[<p>When I first began developing using a Mac I made use of the bundled versions of Apache and PHP that were included in OS X Tiger. This meant I only needed to install MySQL to be able to develop fairly complex websites.</p>
<p>However, as my requirements evolved, I discovered that recompiling PHP to include support for features such as HTML Tidy was going to be a pain in the proverbials. So, following advice from friends, I opted to install another version of Apache, PHP5, and MySQL using MacPorts package management. This required minimal configuration and allowed me to easily activate or deactivate features on install &#8212; and it also allowed me to add to my environment as I learnt new skills; including Python and Django.</p>
<p>Recently, however, this became an issue again, as I attempted to install mod_wsgi in the MacPorts Apache. No matter how hard I tried, I just couldn&#8217;t get it working with more complex Python scripts. At this point, I sought more help from my friends and, after a couple of attempts to rectify the problem, was suggested the movement of my entire development environment to a dedicated virtual machine.</p>
<p>So, thanks to <a href="http://dannyamey.com/">Danny Amey</a> and <a href="http://intranation.com">Brad Wright</a>, I&#8217;m now running a proper Ubuntu server as my development environment and have just as much control over it as I do on my live web server. In fact, the two are pretty much identical; and, best of all, I have access to all the files on my dev server using VMWare shared folders, which means I can use all my favourite OS X tools to create and edit files. I really can&#8217;t advocate this method enough.</p>
<p>For more information on creating such an environment, I recommend reading Brad&#8217;s post, &#8220;<a href="http://intranation.com/entries/2009/03/development-virtual-machines-os-x-using-vmware-and/">development virtual machines on OS X using VMWare and Ubuntu</a>&#8220;.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2009/04/a-better-os-x-development-environment/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2009/04/a-better-os-x-development-environment/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2009/04/a-better-os-x-development-environment/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[Web Servers and Email: Postfix on Ubuntu]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/1F2WS8SX19Y/" />
		<id>http://nefariousdesigns.co.uk/archive/2009/04/web-servers-and-email-postfix-on-ubuntu/</id>
		<updated>2009-04-11T16:16:39Z</updated>
		<published>2009-04-11T16:16:39Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="Email" /><category scheme="http://nefariousdesigns.co.uk" term="Linux" /><category scheme="http://nefariousdesigns.co.uk" term="Server" /><category scheme="http://nefariousdesigns.co.uk" term="UNIX" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[Setting up web servers is an oft-covered subject in the web development blogosphere. However, when I needed to set up a shared web and email server, I discovered that such documentation was somewhat more dispersed. With that in mind, and following the development of an email newsletter at work (in which I demonstrated several email [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2009/04/web-servers-and-email-postfix-on-ubuntu/"><![CDATA[<p>Setting up web servers is an oft-covered subject in the web development blogosphere. However, when I needed to set up a shared web and <em>email</em> server, I discovered that such documentation was somewhat more dispersed. With that in mind, and following the development of an email newsletter at work (in which I demonstrated several email testing techniques that were of interest to some of the other developers), I began drafting a blog post that would hopefully bring some of that information together. Sadly, I never finished.</p>
<p>Due to an ever more stressful workplace and the arrival of another child in the household, I took a somewhat forced break from blogging. This was entirely unintended and I&#8217;ve decided to get back on the wagon again by finishing the aforementioned post.</p>
<p>So here it is; the finished article on setting up Postfix on a shared mail and web server. Please remember that I&#8217;m technically a mail server numpty and probably won&#8217;t have all the answers to questions should you have them. However, feel free to leave them in the comments and hopefully someone out there (or someone I can poke for comment elsewhere) can help you out.</p>
<p><span id="more-180"></span></p>
<h2>A bit of background</h2>
<p>I made the jump from supported, pre-built hosting to entirely self-managed hosting last year. As a result, I soon discovered the need to handle email received by the various hosted domains on my server.</p>
<p>One solution to this problem would be to use <a href="http://www.google.com/apps/intl/en/business/index.html">Google Apps for Business</a>. Too easy, drill sergeant; and also $50 more than I was willing to spend a year. Another solution would be to install my own email server and manage it myself. Despite this idea giving me The Fear&trade;, it also meant I&#8217;d be learning something new &#8212; a buzz I find difficult to ignore at the best of times.</p>
<p>Given those options, I&#8217;m sure it&#8217;s not too hard to figure out which route I took, and the following blog post is a small amount of what I learnt in the process.</p>
<h2>Hostname</h2>
<p>Often, when building a web server, the server hostname is overlooked as unimportant. This is generally because the DNS system provides all the functionality needed when serving files over HTTP. However, when the server is required to handle email, it is important to set a hostname because it is used by the various email protocols as a source and destination identifier; ergo a key component in the identification of spam.</p>
<p>Postfix will let you send and receive mail just fine between accounts on a machine with a fantasy name. However, you cannot use a fantasy hostname in your email address when sending email via the Internet, because no-one would be able to reply to your mail. In fact, more and more sites refuse mail addresses with non-existent domain names.</p>
<p>Further to this, you may want to specify a <em>fully-qualified domain name</em> hostname. A hostname is considered to be a fully qualified domain name (FQDN) if all the labels up to and including the top-level domain name (TLD) are specified. The hostname &#8220;mail.nerfabulousdesigns.co.uk&#8221; terminates with the top-level domain &#8220;co.uk&#8221; and is thus fully-qualified. Depending on the system, an unqualified hostname such as &#8220;server1&#8243; or &#8220;test-server&#8221; may be combined with default domain names in order to determine the fully qualified domain name. However, in most cases, a web server or mail server won&#8217;t be running in that sort of environment.</p>
<p>With all that in mind, it&#8217;s best to use a domain name you can access the DNS records for, as you&#8217;ll want to forward email to it using the MX record. An accepted standard, when working with mail, is to use &#8220;mail.mydomain.com&#8221;, however, in this case, we&#8217;re sharing email and web serving duties on the same box. A better solution would be to come up with any name that you can use to uniquely identify the server in your DNS settings. For the purpose of my examples, I&#8217;m going to work with the hostname &#8220;spartacus.nerfabulousdesigns.co.uk&#8221;.</p>
<h3>DNS for your hostname</h3>
<p>Before I start wading into the installing and configuring the server, it&#8217;s important to get the DNS set up in your DNS manager. So, if the IP address of our server is 123.456.789.123 we&#8217;ll want the following DNS records:</p>
<pre><samp>A Records:
spartacus.nerfabulousdesigns.co.uk -> 123.456.789.123
mail.nerfabulousdesigns.co.uk -> 123.456.789.123

MX Record:
mail.nerfabulousdesigns.co.uk</samp></pre>
<p>Any other domains you want to set up for email only need the following rules:</p>
<pre><samp>A Records:
mail.yourdomain.com -> 123.456.789.123

MX Record:
mail.yourdomain.com</samp></pre>
<p>Once you&#8217;ve saved those changes, and you&#8217;re awaiting DNS propagation, it&#8217;s time to get back to our server.</p>
<h3>Server settings for your hostname</h3>
<p>To find out the current hostname of your server (which is defined during installation), type the following:</p>
<pre><samp>$ <kbd>hostname</kbd></samp></pre>
<p>The <code>hostname</code> command will output the current hostname if you run it without any parameters. If you want to see the fully qualified hostname, type the following:</p>
<pre><samp>$ <kbd>hostname -f</kbd></samp></pre>
<p>To change your hostname temporarily, you can simply enter the new hostname as the first parameter of the hostname command. So, assuming I want to identify my server as &#8220;spartacus&#8221;, I&#8217;d enter the following:</p>
<pre><samp>$ <kbd>hostname spartacus.nerfabulousdesigns.co.uk</kbd></samp></pre>
<p>Now we can check our change:</p>
<pre><samp>$ <kbd>hostname</kbd>
spartacus.nerfabulousdesigns.co.uk</samp></pre>
<p>Huzzah!</p>
<p>Unfortunately, that change will be reset should the machine be rebooted for any reason.</p>
<p>Not-huzzah!</p>
<p>To make the change permanent, you&#8217;ll need to edit the single-line <code>/etc/hostname</code> file:</p>
<pre><samp>$ <kbd>sudo vim /etc/hostname</kbd></samp></pre>
<p>Update it to contain the following:</p>
<pre><samp>spartacus.nerfabulousdesigns.co.uk</samp></pre>
<p>Now you can trigger your change by restarting the hostname daemon:</p>
<pre><samp>$ <kbd>/etc/init.d/hostname.sh start</kbd></samp></pre>
<p>However, you don&#8217;t need to do that just yet since you&#8217;ll probably want to restart your server later on in the process.</p>
<h3>The hosts file</h3>
<p>Next we&#8217;ll need to update the hosts file on the server so that it recognises the new hostname as a referer to the loopback IP 127.0.0.1. To do that, edit the hosts file with the following command:</p>
<pre><samp>$ <kbd>sudo vi /etc/hosts</kbd></samp></pre>
<p>And then update it so that it contains a line similar to this:</p>
<pre><samp>127.0.0.1        spartacus.nerfabulousdesigns.co.uk</samp></pre>
<p>Once this file has been saved, we can do that reboot we were going to do earlier:</p>
<pre><samp>$ <kbd>sudo reboot</kbd></samp></pre>
<p>Once your server is back up, the hostname change is complete. Your server will now use the loopback address when hostname references are used, instead of wasting valuable time checking DNS records.</p>
<h2>Install Postfix</h2>
<p>Now that the server is primed for email, it&#8217;s time to install postfix &#8212; and while we&#8217;re at it, let&#8217;s install mailx, an improved version of the mail email user agent program, and let&#8217;s also confirm we have telnet installed as we&#8217;re going to use it for testing later on:</p>
<pre><samp>$ <kbd>sudo aptitude install postfix mailx telnet</kbd></samp></pre>
<p>As Postfix installs, you&#8217;ll be asked a number of configuration questions:</p>
<p>For &#8220;general type of mail configuration&#8221;, choose:</p>
<pre><samp>Internet Site</samp></pre>
<p>You will then be asked the fully qualified domain name of your server, which in our case is:</p>
<pre><samp>spartacus.nerfabulousdesigns.co.uk</samp></pre>
<p>Once you&#8217;ve done that, the installation is complete. Your web server is now capable of sending email; and to prove it, let&#8217;s just test it from the command line.</p>
<h2>Testing</h2>
<p>Let&#8217;s send an email to a real email address (remember to replace <samp>somebody@somewhere.com</samp> with the real email address of your choice):</p>
<pre><samp>$ <kbd>mail somebody@somewhere.com</kbd></samp></pre>
<p>The mail program will now ask you for a subject. Once you press return, mail will now be accepting the body of your email (albeit without a prompt). To tell the program that you&#8217;ve reached the end of your email body, you&#8217;ll need to place a single full-stop character, &#8220;.&#8221;, on a line by itself (since the return character is perfectly valid in the body of your mail). Finally, the mail program will then ask you for any CC addresses. </p>
<p>Here&#8217;s an example of the complete screen output:</p>
<pre><samp>$ <kbd>mail somebody@somewhere.com</kbd>
Subject: <kbd>Testing my all new email server!</kbd>
<kbd>Red leader, this is mail server. Are you receiving, over?
.</kbd>
Cc:
$</samp></pre>
<p>You won&#8217;t receive any confirmation that the email has been sent &#8212; you should just return to the command prompt &#8212; however, as long as everything was set up correctly, you should have received the email.</p>
<p>The next step is to configure our mail server so that it knows what to do with received email.</p>
<h2>Configuration</h2>
<p>Configuration of a mail server is where all the pain and torment begins; but in this case, I only want to set up mail forwarding &#8212; which takes all the pain and torment away and leaves us with a fairly straight forward, unburdened mail server that&#8217;s using very little disk space. I could usually do this at the DNS level, but I chose not to in case I decided to work with real mail boxes in the future &#8212; and also because I was still relishing the learning experience. If you want to set up something different, I&#8217;m afraid you&#8217;re going to have to look elsewhere for a tutorial because I haven&#8217;t the time (or the patience) to go through the multitude of different set-ups that are possible.</p>
<p>The first step in setting up mail forwarding in Postfix is to create a virtual hash. To do that, we need to create the following file:</p>
<pre><samp>$ <kbd>sudo vim /etc/postfix/virtual</kbd></samp></pre>
<p>And inside that file, we need to define some values. Here&#8217;s how we&#8217;d set up nerfabulousdesigns.co.uk as a mail forwarding domain:</p>
<pre><samp>john@nerfabulousdesigns.co.uk    john.smith@yahoo.com
joe@nerfabulousdesigns.co.uk     joe.bloggs@yahoo.com

# For a catch-all, do the following
@nerfabulousdesigns.co.uk        example@yahoo.com</samp></pre>
<p>Once you&#8217;ve saved that file, run the following command to create the postmap:</p>
<pre><samp>$ <kbd>postmap /etc/postfix/virtual</kbd></samp></pre>
<p>Next you&#8217;ll also need to update this file:</p>
<pre><samp>$ <kbd>sudo vim /etc/postfix/main.cf</kbd></samp></pre>
<p>Add your domain to <code>virtual_alias_domains</code> and your virtual hash to <code>virtual_alias_maps</code> like so:</p>
<pre><samp>virtual_alias_domains = nerfabulousdesigns.co.uk ...other hosted domains...
virtual_alias_maps = hash:/etc/postfix/virtual</samp></pre>
<p>Finally, you&#8217;ll need to do the following to restart Postfix:</p>
<pre><samp>$ <kbd>postfix reload</kbd></samp></pre>
<p>Any emails to the domains or addresses you added to the virtual hash should now be forwarded as expected.</p>
<h2>Telnet</h2>
<p>Finally, let&#8217;s test the email server is working using Telnet. This is a handy little technique for checking everything is as expected, since it will also display responses at every stage of the mail sending process.</p>
<p>You can telnet from any machine that has it installed &#8212; and since we installed it on our server earlier, we can even telnet the server to itself, which might be useful when trying to track down problems.</p>
<p>To begin with, let&#8217;s Telnet to our server over the default <abbr title="Simple Mail Transfer Protocol">SMTP</abbr> port 25:</p>
<pre><samp>$ <kbd>telnet mail.nerfabulousdesigns.co.uk 25</kbd></samp></pre>
<p>Which should trigger a response similar to this:</p>
<pre><samp>Trying 209.20.86.249...
Connected to mail.nerfabulousdesigns.co.uk.
Escape character is '^]'.
220 spartacus.nerfabulousdesigns.co.uk ESMTP Postfix (Ubuntu)</samp></pre>
<p>If the connection was a success, you should receive a 220 <abbr title="Simple Mail Transfer Protocol">SMTP</abbr> reply code. For more information, here&#8217;s <a href="http://www.greenend.org.uk/rjk/2000/05/21/SMTP-replies.html">a handy reference on <abbr title="Simple Mail Transfer Protocol">SMTP</abbr> reply codes</a>.</p>
<p>The next thing we need to do, in the essence of being polite, is greet the mail server. We can do that one of two ways. We can either use the <abbr title="Simple Mail Transfer Protocol">SMTP</abbr> command, <code>HELO</code>:</p>
<pre><samp><kbd>HELO my.local.domain</kbd>
250 spartacus.nerfabulousdesigns.co.uk</samp></pre>
<p>Or we can use the more recent <code>EHLO</code> command, which will return more detailed information about the server:</p>
<pre><samp><kbd>EHLO my.local.domain</kbd>
250-spartacus.nerfabulousdesigns.co.uk
â€¦ More detailed info. hereâ€¦</samp></pre>
<p>Great, so now that we&#8217;ve identified ourselves, we&#8217;re reading to start defining the envelope for our message. First, we need to tell the mail server who the sender is:</p>
<pre><samp><kbd>MAIL FROM:<telnet@nerfabulousdesigns.co.uk></kbd>
250 2.1.0 Ok</samp></pre>
<p>Second, we need to tell the mail server who we&#8217;d like the email delivered to:</p>
<pre><samp><kbd>RCPT TO:joe@nerfabulousdesigns.co.uk</kbd>
250 2.1.5 Ok</samp></pre>
<p>That&#8217;s it; the envelope is now complete. We can now move onto filling our message with data. To do that, we simply use the command <code>DATA</code>, which will then allow us to enter the subject and main content for our message:</p>
<pre><samp><kbd>DATA</kbd>
354 End data with <CR><LF>.<CR><LF>
<kbd>Subject: Test Email
This is a test email.
.</kbd>
250 2.0.0 Ok: queued as 40F438D023</samp></pre>
<p>Our message is complete, and has been queued by the mail server for redistribution to the recipient. We&#8217;re done here, so let&#8217;s quite out of the telnet session:</p>
<pre><samp><kbd>QUIT</kbd>
221 2.0.0 Bye
Connection closed by foreign host.
$ </samp></pre>
<p>And we&#8217;re now back at our original command prompt. If you check the mailbox of your recipient, you should have successfully received the email.</p>
<h2>Summary</h2>
<p>Despite the fact that I could probably have handled email in more efficient ways, I thoroughly enjoyed learning about Postfix and the black magic therein. I&#8217;m sure that some of my peers will have plenty to correct me on, and I sincerely hope they do; as previously stated, this was intended as a learning experience, and learning is what I have done.</p>
<p>Hopefully, some &#8212; if not all &#8212; the techniques used in this article will be of some use to you. Certainly, they have aided me in my understanding of core internet technologies.</p>
<p>Please feel free to comment, question, or to point out flaws with my methods. I hope the discussion is fruitful.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2009/04/web-servers-and-email-postfix-on-ubuntu/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2009/04/web-servers-and-email-postfix-on-ubuntu/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2009/04/web-servers-and-email-postfix-on-ubuntu/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[Practical Django Projects and Django 1.0]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/l91aOe0_SiU/" />
		<id>http://nefariousdesigns.co.uk/archive/2008/09/practical-django-projects-and-django-10/</id>
		<updated>2008-10-24T10:04:32Z</updated>
		<published>2008-09-25T09:41:46Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Books" /><category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="Django" /><category scheme="http://nefariousdesigns.co.uk" term="Python" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[I recently purchased a copy of &#8220;Practical Django Projects&#8220;, by James Bennett, with the intention of diving straight in and learning Django. I&#8217;d prepared for this daring feat of code-ninjutsu [yes, that's the correct spelling] with a crash course in Python via &#8220;Dive Into Python&#8220;, by Mark Pilgrim.
This appears to have been the correct choice, [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2008/09/practical-django-projects-and-django-10/"><![CDATA[<p>I recently purchased a copy of &#8220;<a href="http://www.amazon.co.uk/gp/product/1590599969?ie=UTF8&#038;tag=gamersite-21&#038;linkCode=as2&#038;camp=1634&#038;creative=6738&#038;creativeASIN=1590599969">Practical Django Projects</a>&#8220;, by James Bennett, with the intention of diving straight in and learning Django. I&#8217;d prepared for this daring feat of code-ninjutsu [yes, that's the correct spelling] with a crash course in Python via &#8220;<a href="http://www.amazon.co.uk/gp/product/1590593561?ie=UTF8&#038;tag=gamersite-21&#038;linkCode=as2&#038;camp=1634&#038;creative=6738&#038;creativeASIN=1590593561">Dive Into Python</a>&#8220;, by Mark Pilgrim.</p>
<p>This appears to have been the correct choice, as I&#8217;ve already acquired a confident grasp of the concepts and techniques of Django in less than a few days of playing with it (granted; with the odd reference look-up on <a href="http://www.djangobook.com/">http://www.djangobook.com/</a> and <a href="http://docs.djangoproject.com/en/dev/">http://docs.djangoproject.com/en/dev/</a>).</p>
<p>However, last night it all went a bit wrong when I upgraded my local version of Django from 0.96 to 1.0&hellip;</p>
<p><span id="more-179"></span></p>
<p>Most of my issues were due to the fact that some of the code in the examples, included in <a href="http://www.amazon.co.uk/gp/product/1590599969?ie=UTF8&#038;tag=gamersite-21&#038;linkCode=as2&#038;camp=1634&#038;creative=6738&#038;creativeASIN=1590599969">Practical Django Projects</a>, was now out of date. However, I had expected this (thanks to warnings from <a href="http://cyril.doussin.name/">Cyril Doussin</a> and <a href="http://dynamicflash.com/">Steve Webster</a>) and went about fixing the problems using the informative <a href="http://docs.djangoproject.com/en/dev/releases/1.0-porting-guide/">Porting Guide on the Django documentation site</a>.</p>
<p>Following my extensive fixes, I was still experiencing issues when decoupling the Admin class from its relevant model. In most cases, this was a relatively easy process, but in one particular situation, where I had used <code>edit_inline</code> and needed to update the method to use the new InlineModelAdmin objects, I had a slightly confusing issue: I needed to add the InlineModelAdmin object to one of the django.contrib applications â€” FlatPage â€” to get the SearchKeyword application to work.</p>
<p>After a short period googling, I found an interesting, well-written blog post by <a href="http://jasonism.org/">Jason Broyles</a>, &#8220;<a href="http://jasonism.org/weblog/2008/aug/04/adding-inlinemodeladmin-djangocontrib-application/">Add InlineModelAdmin to a django.contrib app</a>&#8220;. Unsurprisingly, it seemed others had had exactly the same issue.</p>
<p>Jason&#8217;s final model.py and admin.py files were as follows:</p>
<pre><code># models.py

from django.db import models
from django.contrib.flatpages.models import FlatPage

class SearchKeyword(models.Model):
    keyword = models.CharField(max_length=50)
    page = models.ForeignKey(FlatPage)

    def __unicode__(self):
        return self.keyword</code></pre>
<pre><code># admin.py

from django.contrib import admin
from cms.search.models import SearchKeyword
from django.contrib.flatpages.models import FlatPage
from django.utils.translation import ugettext_lazy as _

class SearchKeywordInline(admin.StackedInline):
    model = SearchKeyword
    extra = 3
    max_num = 6

class FlatPageAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {'fields': ('url', 'title', 'content', 'sites')}),
        (_('Advanced options'), {'classes': ('collapse',), 'fields': ('enable_comments', 'registration_required', 'template_name')}),
    )
    list_display = ('url', 'title')
    list_filter = ('sites', 'enable_comments', 'registration_required')
    search_fields = ('url', 'title')
    inlines = [SearchKeywordInline,]

admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin)</code></pre>
<p>Jason followed these examples with the following explanation:</p>
<blockquote cite="http://jasonism.org/weblog/2008/aug/04/adding-inlinemodeladmin-djangocontrib-application/"><p>The above admin.py file will make it so the SearchKeyword model is accessible in the FlatPages admin interface. It does this by first creating the SearchKeywordInline class and adding it to a new FlatPage ModelAdmin function. I also didn&#8217;t want to loose out on any of the extra options from the default django.contrib.flatpages ModelAdmin so I copied lines 6 and 14-20 from it and added the code to my file. Line 23 then unregisters the default FlatPage ModelAdmin and line 24 registers this new one with my inlines included.</p></blockquote>
<p>This solution fixed my problems, however I was concerned that copying and pasting code from <code>django.contrib.flatpages ModelAdmin</code> to <code>admin.py</code> was a massively inelegant solution. With that in mind, I came up with the following solution using inheritance:</p>
<pre><code># admin.py

from django.contrib import admin
from cms.search.models import SearchKeyword
from django.contrib.flatpages.models import FlatPage
from django.contrib.flatpages.admin import FlatPageAdmin
from django.utils.translation import ugettext_lazy as _

class SearchKeyword_Inline(admin.TabularInline):
	model = SearchKeyword
	extra = 3
	max_num = 6

class FlatPageAdmin(FlatPageAdmin):
 	inlines = [SearchKeyword_Inline]

admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin)</code></pre>
<p>This worked perfectly.</p>
<p>As a final note, I&#8217;d just like to thank Jason for posting his solution; without that much needed information, I probably would have spent a lot more time trying to fix the issue than was really required. It just goes to show that developers that blog are a huge benefit to confused developers everywhere.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2008/09/practical-django-projects-and-django-10/#comments" thr:count="4" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2008/09/practical-django-projects-and-django-10/feed/atom/" thr:count="4" />
		<thr:total>4</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2008/09/practical-django-projects-and-django-10/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[The Joy of UNIX]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/7108kRNsRYg/" />
		<id>http://nefariousdesigns.co.uk/archive/2008/09/the-joy-of-unix/</id>
		<updated>2008-09-23T12:33:20Z</updated>
		<published>2008-09-23T12:33:20Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="Linux" /><category scheme="http://nefariousdesigns.co.uk" term="Mac OS X" /><category scheme="http://nefariousdesigns.co.uk" term="Reference" /><category scheme="http://nefariousdesigns.co.uk" term="Server" /><category scheme="http://nefariousdesigns.co.uk" term="UNIX" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[One of the best things about developing from a Mac is the fact that it is a UNIX-based operating system. This means that my development environment is a far closer match to my production hosting environment (Linux) than it was when I was developing under Windows.
The net result of this shift in paradigm is a [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2008/09/the-joy-of-unix/"><![CDATA[<p>One of the best things about developing from a Mac is the fact that it is a UNIX-based operating system. This means that my development environment is a far closer match to my production hosting environment (Linux) than it was when I was developing under Windows.</p>
<p>The net result of this shift in paradigm is a rapidly expanding knowledge of the command-set and OS structure. The exposure to UNIX has done me the world of good; particularly in regard to web development and server management. Sadly, the relative shelter I was accustomed to at Rentokil Initial, thanks to the inclusion of immensely talented and helpful server admins within our team, had hindered my development as a web developer, and provoked ridicule at the hands of my fellow Y! EU developers (in the nicest possible way, of course).</p>
<p>With all that in mind, here&#8217;s a bunch of stuff I&#8217;ve learnt that might be a useful reference resource&hellip;</p>
<p><span id="more-176"></span></p>
<h2>Books</h2>
<p><a href="http://www.amazon.co.uk/gp/product/013937681X?ie=UTF8&#038;tag=gamersite-21&#038;linkCode=as2&#038;camp=1634&#038;creative=6738&#038;creativeASIN=013937681X"><img src='http://nefariousdesigns.co.uk/blog/images/41qm4speaal_sl160_.jpg' alt='' class='pos1 framed' /></a> The first book I&#8217;d recommend reading for a good grounding in UNIX is &#8220;<a href="http://www.amazon.co.uk/gp/redirect.html?ie=UTF8&#038;location=http%3A%2F%2Fwww.amazon.co.uk%2FUnix-Programming-Environment-Prentice-Hall-Software%2Fdp%2F013937681X%3Fie%3DUTF8%26s%3Dbooks%26qid%3D1222162055%26sr%3D8-1&#038;tag=gamersite-21&#038;linkCode=ur2&#038;camp=1634&#038;creative=6738"><strong>The UNIX Programming Environment</strong></a>&#8220;, by Brian W. Kernighan and Rob Pike. Although this is book is over 20 years old, it&#8217;s still highly relevant; Kernighan and Pike both worked at Bell Labs during the development of UNIX and contributed greatly to the OS and its school of thought. The book covers a huge expanse of subjects, from the basics through to full program development.</p>
<p><a href="http://www.amazon.co.uk/gp/product/0596100299?ie=UTF8&#038;tag=gamersite-21&#038;linkCode=as2&#038;camp=1634&#038;creative=6738&#038;creativeASIN=0596100299"><img src="http://nefariousdesigns.co.uk/blog/images/51w740pbx7l_sl160_.thumbnail.jpg" alt="" class="pos2 framed" /></a>The second book, as is so often the case, is published by O&#8217;Reilly. &#8220;<a href="http://www.amazon.co.uk/gp/product/0596100299?ie=UTF8&#038;tag=gamersite-21&#038;linkCode=as2&#038;camp=1634&#038;creative=6738&#038;creativeASIN=0596100299"><strong>UNIX in a Nutshell</strong></a>&#8220;, by Arnold Robbins, is a great, up-to-date examination of the operating system, including a vast array of information perfect for beginners and experienced users alike.</p>
<p>Both of these books should provide enough knowledge for you to feel safe getting down and dirty with UNIX; so let&#8217;s dive in with a look at some useful keyboard and command line shortcuts:</p>
<h2>Keyboard and Command Line Shortcuts</h2>
<p>The following are common keyboard and command line shortcuts for use in UNIX-based systems. Please note that all UNIX variants differ and some of these shortcuts may not be available to you, or may require different syntax or keystrokes.</p>
<h3>Keyboard Shortcuts</h3>
<p>To begin with, here&#8217;s a list of useful keyboard shortcuts:</p>
<ul>
<li><kbd>CTRL + A</kbd> â€” Moves the cursor to the beginning of the line.</li>
<li><kbd>CTRL + E</kbd> â€” Moves the cursor to the end of the line.</li>
<li><kbd>CTRL + U</kbd> â€” Erases the complete line.</li>
<li><kbd>CTRL + B</kbd> â€” Moves the cursor backward one character.</li>
<li><kbd>CTRL + F</kbd> â€” Moves the cursor forward one character.</li>
<li><kbd>CTRL + H</kbd> â€” Erase one character. Similar to pressing backspace.</li>
<li><kbd>CTRL + W</kbd> â€” Deletes the last word typed.</li>
<li><kbd>CTRL + C</kbd> â€” Cancels the currently running command.</li>
<li><kbd>CTRL + D</kbd> â€” Logs out of the current session.</li>
</ul>
<p>Most of those are self-explanatory, but you&#8217;ll wonder how you lived without them soon enough.</p>
<h3>Command Line Shortcuts</h3>
<p>Next, let&#8217;s take a look at some useful command line shortcuts, starting with <em>directory navigation</em>:</p>
<ul>
<li><code>~</code> â€” References the current user&#8217;s home directory.</li>
<li><code>.</code> â€” References the current directory.</li>
<li><code>..</code> â€” References the parent of the current directory.</li>
</ul>
<p>Here&#8217;s a quick demonstration to hopefully make their use a little clearer (the names have been changed to protect the innocent). Note, this example uses several UNIX commands; <code>cd</code> = change directory, <code>pwd</code> = print working directory, <code>ls</code> = list contents of directory, and <code>cp</code> = copy files:</p>
<pre><code>$ pwd
/Users/timbo
$ cd /var/www/nefarious/
$ pwd
/var/www/nefarious
$ cd ..
$ pwd
/var/www
$ ls
a-website   another-website   nefarious
$ cd /var/www2
$ pwd
/var/www2
$ ls
$ cp /var/www/* ./
$ ls
a-website   another-website   nefarious
$ cd ~
$ pwd
/Users/timbo</code></pre>
<p>Now that we can effectively navigate the directory structure, let&#8217;s have a look at the incredibly useful history utility and its command line shortcuts:</p>
<ul>
<li><code>!!</code> â€” Re-run your last command.</li>
<li><code>!10</code> â€” Re-run line number 10 in the history.</li>
<li><code>!-n</code> â€” Refer to the current command line minus n.</li>
<li><code>!?str?</code> â€” Refer to the most recent command containing str (string).</li>
<li><code>!str</code> â€” Re-run the last command ran that started with str (string).</li>
<li><code>!$</code> â€” Re-use the parameters from the previous command.</li>
</ul>
<p>I won&#8217;t go into detail on each one of those, but here&#8217;s an example of the last one â€” arguably the most useful â€” in action:</p>
<pre><code>$ pwd
/Users/timbo
$ ls projects/django/
cms    coltrane    davis
$ cd !$
cd projects/django/
$ pwd
/Users/timbo/projects/django</code></pre>
<h2>Summary</h2>
<p>This is just a quick reference to some useful shortcuts; I could have delved deeper into setting up aliases in your profiles and making your prompt look pretty, but I thought I&#8217;d save that for a possible follow up post.</p>
<p>I hope somebody out there finds this useful; and feel free to add your own tips and tricks in the comments.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2008/09/the-joy-of-unix/#comments" thr:count="7" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2008/09/the-joy-of-unix/feed/atom/" thr:count="7" />
		<thr:total>7</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2008/09/the-joy-of-unix/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[Back on the horse]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/gvr-8V9aXY0/" />
		<id>http://nefariousdesigns.co.uk/archive/2008/08/back-on-the-horse/</id>
		<updated>2008-08-10T11:07:05Z</updated>
		<published>2008-08-10T11:03:01Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Personal" />		<summary type="html"><![CDATA[Right then. After almost a years hiatus, it&#8217;s about time I got back into this blogging lark. Unfortunately, I have a plethora of subjects I&#8217;d like to cover and no idea where to start!
I think I&#8217;ll get the personal stuff out of the way first and then I can think about planning the web development [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2008/08/back-on-the-horse/"><![CDATA[<p>Right then. After almost a years hiatus, it&#8217;s about time I got back into this blogging lark. Unfortunately, I have a plethora of subjects I&#8217;d like to cover and no idea where to start!</p>
<p>I think I&#8217;ll get the personal stuff out of the way first and then I can think about planning the web development stuff&hellip;</p>
<p><span id="more-175"></span></p>
<p>The biggest news is that <a href="http://flickr.com/photos/nefarioustim/2587002110/">I&#8217;m going to be a father again</a>, but thankfully this time it&#8217;s just the one baby. Further to that, my twin girls are now 14 months old and <em>extremely</em> mobile (in horizontal <em>and</em> vertical directions &#8212; we&#8217;ve had to rearrange the furniture to discourage climbing).</p>
<p>I&#8217;m still working at <a href="http://www.yahoo.co.uk">Yahoo!</a> in London and, despite the odd crisis of morale, am still enjoying working with what is arguably the best corporate web development team in the world. It&#8217;s a shame my commute is 2 hours each way otherwise I&#8217;d also be enjoying the more social aspects of the team as well (but since most evenings are spent on <a href="http://www.xbox.com">Xbox Live</a> with my colleagues, I&#8217;m not missing <em>too</em> much).</p>
<p>I also found out that I have <a href="http://en.wikipedia.org/wiki/Coeliac_disease">Coeliac Disease</a>; a harsh name for what is, effectively, an allergy to gluten (found in wheat, barley, oats, and rye). This hasn&#8217;t been all that difficult to adapt to since my sister has been diagnosed since she was 3 years old &#8212 ;and my dad worked out, shortly after she was diagnosed, that he is too. This basically means that I&#8217;ve been used to shopping, cooking, and dining-out with Coeliacs since a very early age. Want to know the worst part of the allergy? I can no longer drink beer. Sweet, sweet beer. I really miss a tasty pint of <a href="http://www.guinness.com">Guinness</a>.</p>
<p>Finally, I&#8217;ve also undertaken a few personal projects: a new rock band, a (possible) book on web development, a cooking blog (no link because it&#8217;s not up yet), and various other things.</p>
<p>So that&#8217;s the past year in a nutshell. I&#8217;m sure there&#8217;s lots more I could&#8217;ve written but it&#8217;s easier to just condense. Now I can get started on the web development related blog posts&hellip;</p>
<p>&hellip; although I <em>still</em> have no idea where to start!</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2008/08/back-on-the-horse/#comments" thr:count="4" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2008/08/back-on-the-horse/feed/atom/" thr:count="4" />
		<thr:total>4</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2008/08/back-on-the-horse/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[JavaScript Module Pattern Variations]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/NzvZTFKlwsM/" />
		<id>http://nefariousdesigns.co.uk/archive/2007/08/javascript-module-pattern-variations/</id>
		<updated>2007-08-31T12:37:32Z</updated>
		<published>2007-08-31T09:02:10Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="JavaScript" /><category scheme="http://nefariousdesigns.co.uk" term="Tutorials" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[The JavaScript Module Pattern is a handy pattern for JavaScript singletons. It allows a developer to scope variables and methods to a given module with both private and public visibility.
Originally proposed by Douglas Crockford (and blogged on the YUI blog by Eric Miraglia), the Module Pattern has recently been through several iterations of pimpage (look [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2007/08/javascript-module-pattern-variations/"><![CDATA[<p>The JavaScript Module Pattern is a handy pattern for JavaScript singletons. It allows a developer to scope variables and methods to a given module with both private and public visibility.</p>
<p><a href="http://yuiblog.com/blog/2007/06/12/module-pattern/">Originally proposed by Douglas Crockford (and blogged on the YUI blog by Eric Miraglia)</a>, the Module Pattern has recently been through several iterations of pimpage (look Ma &#8212; a new buzzword!) at the hands of Christian Heilmann; the first entitled &#8220;<a href="http://www.wait-till-i.com/index.php?p=467">Show love to the Module Pattern</a>&#8221; and the second, &#8220;<a href="http://www.wait-till-i.com/index.php?p=476">Again with the Module Pattern</a>&#8220;. Before reading this post, I&#8217;d recommend you read all of these articles otherwise this is going to make very little sense!</p>
<p>Having used the pattern quite regularly over the last six months or so, I&#8217;d like to add my two-pennies-worth to the discussion with a couple of variations on the theme&hellip;</p>
<p><span id="more-171"></span></p>
<h2>Module Pattern in the Pub</h2>
<p>One of Christian&#8217;s evolutions of the Module Pattern involves creating an object entitled <code>pub</code> as a private member of the module. This is then returned as public instead of the anonymous object that Douglas first proposed. I&#8217;m a big fan of this method because it solves a large number of namespace issues when it comes to dealing with private and public members from within our module. Once again, this is all explained in greater detail in Christian&#8217;s post.</p>
<p>The one thing I <em>wasn&#8217;t</em> too keen on, when Christian showed me his method, is the fact that we lose a level of indentation &#8212; something that Christian actually quotes as a <em>positive</em> feature. I guess this comes down to developer preference but I&#8217;ve always liked the fact that that level of indentation allows me to differentiate between the private and public space of the module.</p>
<p>With this in mind, here&#8217;s my slight variation on Chris&#8217; original theme:</p>
<pre><code>NEF.FridayDrinks = function () {
  function purchaseBeer() {
  }

  function drink(beer) {
  }

  var pub = {
    sobriety: 10,
    getRoundIn: function(peoplecount) {
      var trayOfDrinks = new Array();
      for (var i = 0; i < peoplecount; i++) {
        trayOfDrinks.push(purchaseBeer());
      }
      return trayOfDrinks;
    },
    getSlyOne: function() {
      drink(purchaseBeer());
    },
    getDrunk: function() {
      do {
        pub.getSlyOne();
        pub.sobriety--;
      } while (pub.sobriety > 0);
    }
  };
  return pub;
}();

var drinks = NEF.FridayDrinks.getRoundIn();
NEF.FridayDrinks.getSlyOne();
NEF.FridayDrinks.getDrunk();</code></pre>
<p>The difference between my method and Christian&#8217;s is that, where Chris declares an empty <code>pub</code> object with the object literal and then declares each public method as a property of <code>pub</code>, I declare all public methods <em>within</em> the <code>pub</code> object. It&#8217;s a tiny tiny difference, but it brings back that level of indentation we lost without losing any of the added usability of Christian&#8217;s method.</p>
<h2>Module Pattern Curry</h2>
<p>Often, when working with the Module Pattern, you&#8217;ll find yourself with only a single public method &#8212; usually some form of initialisation script (and, funnily enough, usually called &#8220;init&#8221;). This is because there isn&#8217;t often a need for multiple public methods as most modules are fairly self-contained.</p>
<p>For this reason, I decided to try returning just the method itself; much like I would if I was currying my JavaScript function (although not <em>exactly</em> the same way; for more info check out <a href="http://www.svendtofte.com/code/curried_javascript/">&#8220;Curried Javascript&#8221; on svendtofte.com</a>). In this case, we no longer create that public object and, as a result, save a little bit of fuss (and possibly, a little bit of memory too &#8212; bonus!), and for all you filesize facists, you&#8217;ve knocked out a few lines of code too.</p>
<p>Here&#8217;s an example:</p>
<pre><code>NEF.MakeTeaNotLove = function() {
  function getMug() {
    &hellip;
  }
  function addTeabag() {
    &hellip;
  }
  function addBoilingWater() {
    &hellip;
  }
  function addMilk(amount) {
    &hellip;
  }
  function addSugar(amount) {
    &hellip;
  }
  function stir() {
    &hellip;
  }
  return function(milk, sugar) {
    getMug();
    addTeabag();
    addBoilingWater();
    addMilk(milk);
    addSugar(sugar);
    stir();
  };
}();

NEF.MakeTeaNotLove(1, 3);</code></pre>
<p>As you can see, when we call the Module Pattern, rather than having to call an init() member, we can just pass the parameters straight to the returned function. Nice.</p>
<h2>Summary</h2>
<p>Obviously, one of my examples is only suitable for a particular implementation, and the other simply comes down to developer preference, but hopefully somebody out there will find either one of them useful in some way.</p>
<p>Ultimately, it just goes to show how potentially versatile the JavaScript Module Pattern really is. In a matter of months there have been a number of reworkings, bastardisations, and variations. This is just the sort of thing I love about the JavaScript community &#8212; the evolution of code.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2007/08/javascript-module-pattern-variations/#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2007/08/javascript-module-pattern-variations/feed/atom/" thr:count="5" />
		<thr:total>5</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2007/08/javascript-module-pattern-variations/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[Fixing label in Safari]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/O8VDJKlZu7I/" />
		<id>http://nefariousdesigns.co.uk/archive/2007/08/fixing-label-in-safari/</id>
		<updated>2007-08-30T09:48:23Z</updated>
		<published>2007-08-30T09:46:33Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Accessibility" /><category scheme="http://nefariousdesigns.co.uk" term="Browsers" /><category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="JavaScript" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[Safari, the excellent WebKit-based browser from Apple, has long neglected to include functionality that activates a form element (such as an input, a textarea, a select etc.) when its relevant label is clicked.
Although this behaviour has been fixed in the beta of version 3, any users still browsing with version 2 or below still suffer [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2007/08/fixing-label-in-safari/"><![CDATA[<p><a href="http://www.apple.com/safari/">Safari</a>, the excellent WebKit-based browser from Apple, has long neglected to include functionality that activates a form element (such as an <code>input</code>, a <code>textarea</code>, a <code>select</code> etc.) when its relevant <code>label</code> is clicked.</p>
<p>Although this behaviour has been fixed in the beta of version 3, any users still browsing with version 2 or below still suffer this needless blight on web accessibility.</p>
<p>I&#8217;ve recently reworked the JavaScript used in <a href="http://nascentguruism.com/journal/search-and-ye-shall-fail">Steve Marshall&#8217;s tasty channelled search solution</a>, which requires the <code>label</code> to be clickable, as it hides the corresponding radio <code>input</code>. For this reason, I&#8217;ve written a quick bit of JavaScript to activate this behaviour.</p>
<p><span id="more-172"></span></p>
<h2>The Requirements</h2>
<p>As a Yahoo! developer, I&#8217;ve written this implementation using the YUI JavaScript library. There&#8217;s really no reason why you couldn&#8217;t re-jig it to work with any other JS library &#8212; including one you&#8217;ve written yourself.</p>
<p>The YUI objects we will require are: <a href="http://developer.yahoo.com/yui/yahoo/">the YAHOO Global Object</a> and <a href="http://developer.yahoo.com/yui/event/">the Event Utility</a>. To include these files (in their minified form), insert the following lines of code in the <code>head</code> of your html document:</p>
<pre><code>&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.3.0/build/yahoo/yahoo-min.js" &gt;&lt;/script&gt;
&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.3.0/build/event/event-min.js" &gt;&lt;/script&gt;</code></pre>
<p>Alternatively, if you wish to include more of the YUI objects, you can use one of the following files:</p>
<pre><code>&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.3.0/build/yahoo-dom-event/yahoo-dom-event.js"&gt;&lt;/script&gt;</code>

or

<code>&lt;script type="text/javascript" src="http://yui.yahooapis.com/2.3.0/build/utilities/utilities.js"&gt;&lt;/script&gt;</code></pre>
<p>The <code>yahoo-dom-event.js</code> file contains only the YAHOO Global Object, <a href="http://developer.yahoo.com/yui/dom/">the DOM collection</a>, and the Event Utility.</p>
<p>The <code>utilities.js</code> file includes the YAHOO Global Object, the DOM collection, the Event Utility, <a href="http://developer.yahoo.com/yui/element/">the Element utility</a>, <a href="http://developer.yahoo.com/yui/connection/">the Connection Manager</a>, <a href="http://developer.yahoo.com/yui/dragdrop/">the Drag &amp; Drog utility</a>, and <a href="http://developer.yahoo.com/yui/animation/">the Animation utility</a>.</p>
<p>Personally, I tend to include the utilities.js file so that I have as much of the YUI functionality included as I may need. In the essence of avoiding script bloat though, I would recommend including only what you need.</p>
<h2>The Method</h2>
<p>We want to activate a form element when its corresponding label is clicked, so we need to bind an <code>onclick</code> event to any <code>label</code> elements within our page. To do this, we can either loop through all <code>label</code> elements in the <acronym title="Document Object Model">DOM</acronym>, and attach a separate event to each of them; or we can attach a single <code>onclick</code> event to the <code>body</code> of our page and use &#8220;<a href="http://icant.co.uk/sandbox/eventdelegation/">event delegation</a>&#8221; to discover our target element (the <code>label</code>) &#8212; a nice side effect of &#8220;event bubbling&#8221;.</p>
<p>If we click a <code>label</code> element in our page, the onclick event doesn&#8217;t occur on just that element alone; it bubbles up the DOM tree through each of the <code>label</code> element&#8217;s parents. This means an onclick event will fire on the <code>form</code> element, any container elements (<code>div</code> elements, for example), and finally the <code>body</code> element because, in effect, we&#8217;ve clicked all these elements as well.</p>
<p>Event delegation is the process of discovering the element at the bottom of the event bubbling tree &#8212; the &#8220;target&#8221; element. This is fairly straight forward and requires only a few lines of code, whether you&#8217;re using a JavaScript library or not.</p>
<p>Using event delegation will require less code, less memory, and will ultimately run much faster. This is because we do not need to discover all <code>label</code> elements in the page in one go. If we used the other method, our script would become slower and slower the more <code>label</code> elements were included in the page.</p>
<p>Once we have our target element, we can make sure it&#8217;s a <code>label</code>, obtain the form element it&#8217;s related to, and finally activate that element.</p>
<h2>The Code</h2>
<p>Firstly, we need to create our namespace. In this case, I&#8217;ve decided to create an extra layer entitled &#8220;browserfix&#8221; because we&#8217;re essentially fixing an oversight in the browser. Creating the extra layer means that I could possibly bind other browser fixes to the same namespace (although, if we were trying to improve <acronym title="Microsoft Internet Explorer">IE</acronym>, that namespace could get pretty big).</p>
<p>To create our namespace, we do the following:</p>
<pre><code>NEF = window.NEF || {};
NEF.browserfix = window.NEF.browserfix || {};</code></pre>
<p>This either reuses existing objects, or creates new ones using the object literal.</p>
<p>Next we bind a method to our browserfix object to encapsulate our code:</p>
<pre><code>NEF.browserfix.Label = function() {
  &hellip;
}</code></pre>
<p>The first thing our method needs to do is bind an event to the <code>body</code> element of our page. To do this, we use the <code>addListener</code> method of the YUI Event Utility:</p>
<pre><code>YAHOO.util.Event.addListener(document.body, "click", function(e) {
  &hellip;
});</code></pre>
<p><a href="http://developer.yahoo.com/yui/docs/YAHOO.util.Event.html#addListener">The <code>addListener</code> method</a> expects three parameters by default; the element we wish to attach our event listener to (<code>document.body</code>), the event we&#8217;re listening for (&#8221;click&#8221; &#8212; we remove the &#8220;on&#8221; because only certain specific browsers require it and the <code>addListener</code> method will handle that for us), and the function we want to bind to that event (in this case, an anonymous &#8212; or &#8220;lambda&#8221; &#8212; function). We can also pass an arbitrary object to that function (should it require parameters), or scope the execution of our listener to a specific object. In this case, we&#8217;re not doing either of those.</p>
<p>Now we&#8217;ve bound a function to the event we need to populate it with some functionality. Incidentally, the <code>e</code> parameter that is passed to our function is an identifier of type &#8220;Event&#8221;. This is a special object that contains contextual information about the event. You can find out more about this in <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventListener">the W3C docs for the EventListener interface</a>.</p>
<p>The first thing we need to do is work out which element we originally clicked; which is surprisingly straightforward. Using the getTarget method of the YUI Event Utility, we can get that element in a single line &#8212; in fact, without the YUI, this code is still surprisingly simple; the YUI just sorts out all those nasty cross-browser differences for us:</p>
<pre><code>YAHOO.util.Event.addListener(document.body, "click", function(e) {
  var target = YAHOO.util.Event.getTarget(e);
  &hellip;
});</code></pre>
<p>The <code>getTarget</code> method returns the element at the bottom of our event bubbling tree and requires only a single parameter; that special &#8220;Event&#8221; object I was talking about earlier. It needs this to identify which event we&#8217;re tracking. In effect, we&#8217;re passing the event from function to function.</p>
<p>If you&#8217;re interested in the code behind <code>getTarget</code>, I&#8217;d recommend delving into the <a href="http://developer.yahoo.com/yui/docs/Event.js.html">YUI Event Utility code in the API documentation</a>.</p>
<p>Now that we&#8217;ve obtained our clicked element, we need to check to see whether it&#8217;s a <code>label</code>; and if it isn&#8217;t, we return harmlessly &#8212; allowing default behaviour and other events to continue regardless. To do this, we&#8217;ll do a comparison on the <code>tagName</code> property of the element, which we&#8217;ll convert to uppercase to combat case sensitivity:</p>
<pre><code>if (target.tagName &#038;&#038; target.tagName.toUpperCase() !== "LABEL") {
  return;
}</code></pre>
<p>To force a best practice of using <em>explicitly</em> defined label elements, we make the assumption that the <code>htmlFor</code> property will exist. If it doesn&#8217;t, the JavaScript will throw an error &#8212; which is a good thing. Obviously, we could check for the existence of the htmlFor property, or even write a DOM walking loop to handle <em>implicitly</em> defined label elements; but, to be honest, that would be slow and cumbersome, and would allow for a situation we don&#8217;t really want. This assumption allows us to return a <em>new</em> target element; that which is referred to in the <code>for</code> attribute of the opening <code>label</code> tag in our HTML:</p>
<pre><code>target = document.getElementById(target.htmlFor);</code></pre>
<p>Finally, we need to activate our new target element. For most elements, this will involve simply firing the <code>focus</code> method, but if our element is an <code>input</code> of <code>type</code> &#8220;radio&#8221; or &#8220;checkbox&#8221;, we&#8217;ll need to fire the <code>click</code> method:</p>
<pre><code>if (target) {
  if (target.type) {
    switch (target.type) {
      case "radio":
      case "checkbox":
        target.click();
        break;
      default:
        target.focus();
        break;
    }
  } else {
    target.focus();
  }
}</code></pre>
<p>First we check for the existence of the target element &#8212; if it doesn&#8217;t exist, we don&#8217;t want to attempt doing anything. Next we check for the existence of a <code>type</code> property &#8212; this will tell us whether we&#8217;re dealing with an <code>input</code> element or not. If we <em>are</em> dealing with an <code>input</code> element, we perform a <code>switch</code> statement on the <code>type</code> property to ascertain what sort of <code>input</code> we&#8217;re dealing with. If we&#8217;re dealing with a &#8220;radio&#8221; or a &#8220;checkbox&#8221;, we utilise the fall-through behaviour of the <code>switch</code> statement to fire the <code>click</code> method. Also, because we&#8217;re using fall-through, we make sure we supply the <code>switch</code> statement with a <code>default</code> clause that fires the <code>focus</code> method. Finally, if our target <em>doesn&#8217;t</em> have the <code>type</code> property, we also fire the <code>focus</code> method.</p>
<p>Lastly, we run our function when the DOM is in a usable state, using the <a href="http://developer.yahoo.com/yui/event/#ondomready">YUI onDOMReady method</a>:</p>
<pre><code>YAHOO.util.Event.onDOMReady(NEF.browserfix.Label);</code></pre>
<p>Rather than waiting for a <code>window.onload</code> event (which will have to wait for images to load etc.), this will trigger our function as soon as the DOM is loaded thus making sure the behaviour is available as soon as possible.</p>
<p>So here&#8217;s all that code in full:</p>
<pre><code>NEF = window.NEF || {};
NEF.browserfix = window.NEF.browserfix || {};
NEF.browserfix.Label = function() {
  YAHOO.util.Event.addListener(document.body, "click", function(e) {
    var target = YAHOO.util.Event.getTarget(e);
    if (target.tagName &#038;&#038; target.tagName.toUpperCase() !== "LABEL") {
      return;
    }
    target = document.getElementById(target.htmlFor);
    if (target) {
      if (target.type) {
        switch (target.type) {
          case "radio":
          case "checkbox":
            target.click();
            break;
          default:
            target.focus();
            break;
        }
      } else {
        target.focus();
      }
    }
  });
};

YAHOO.util.Event.onDOMReady(NEF.browserfix.Label);</code></pre>
<p>And for anyone browsing with Safari, <a href="http://nefariousdesigns.co.uk/projects/labelfix/">here&#8217;s a handy demo of <code>NEF.browserfix.Label</code> in action</a>&hellip;</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2007/08/fixing-label-in-safari/#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2007/08/fixing-label-in-safari/feed/atom/" thr:count="2" />
		<thr:total>2</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2007/08/fixing-label-in-safari/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Tim</name>
						<uri>http://nefariousdesigns.co.uk/</uri>
					</author>
		<title type="html"><![CDATA[AjaxEvent: Using YUI custom events with Ajax]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/nefariousdesigns/~3/FEy1sCNGg68/" />
		<id>http://nefariousdesigns.co.uk/archive/2007/07/ajaxevent-using-yui-custom-events-with-ajax/</id>
		<updated>2007-07-13T16:14:47Z</updated>
		<published>2007-07-13T08:58:27Z</published>
		<category scheme="http://nefariousdesigns.co.uk" term="Ajax" /><category scheme="http://nefariousdesigns.co.uk" term="Development" /><category scheme="http://nefariousdesigns.co.uk" term="JavaScript" /><category scheme="http://nefariousdesigns.co.uk" term="Web" />		<summary type="html"><![CDATA[Recently, I&#8217;ve been working on some fairly Ajax intensive pages and, because I&#8217;m working in a team environment, the need arose for a simple bit of script to handle all the different Ajax &#8220;events&#8221;. This script needed to be small yet easy to implement
Enter the YUI. *cue Enter The Dragon theme*
So here&#8217;s a tasty little [...]]]></summary>
		<content type="html" xml:base="http://nefariousdesigns.co.uk/archive/2007/07/ajaxevent-using-yui-custom-events-with-ajax/"><![CDATA[<p>Recently, I&#8217;ve been working on some fairly Ajax intensive pages and, because I&#8217;m working in a team environment, the need arose for a simple bit of script to handle all the different Ajax &#8220;events&#8221;. This script needed to be small yet easy to implement</p>
<p>Enter the <a href="http://developer.yahoo.com/yui/"><acronym title="Yahoo! User Interface library">YUI</acronym></a>. *cue Enter The Dragon theme*</p>
<p>So here&#8217;s a tasty little script that wraps Ajax requests and a <acronym title="Yahoo! User Interface library">YUI</acronym> Custom Event in an instantiable object that works as an Ajax <acronym title="Data Access Object">DAO</acronym>&hellip;</p>
<p><span id="more-169"></span></p>
<h2>The Concept</h2>
<h3>Ajax</h3>
<p>Ajax is a buzz-word. It originally stood for &#8220;Asynchronous JavaScript And XML&#8221;, however, these days it tends to encompass any form of remote-scripting; whether it returns XML or not.</p>
<p>Personally, I&#8217;m not a big fan of the term, preferring to call it &#8220;remote scripting&#8221; like I always have &#8212; however, sometimes buzz-words can work to your advantage when you&#8217;re trying to sell something to the money men, your bosses, or, indeed, the search engines.</p>
<p>If you want to read up on Ajax, I&#8217;d recommend starting with <a href="http://www.adaptivepath.com/publications/essays/archives/000385.php">Jesse James Garrett&#8217;s seminal article, &#8220;Ajax: a new approach to Web Applications&#8221;</a>; it&#8217;s a good introduction to the concepts.</p>
<p>Following that, I&#8217;d recommend dipping into the <a href="http://developer.mozilla.org/en/docs/AJAX"><acronym title="Mozilla Developer Center">MDC</acronym> Ajax documentation</a> as it forms a sound base to start from.</p>
<p>Finally, it&#8217;s worth pointing out that any good JavaScript library will contain some form of Ajax handler to make all that cross-browser nonsense a little easier to chew. In this script, I&#8217;ll be utilising the excellent <a href="http://developer.yahoo.com/yui/connection/"><acronym title="Yahoo! User Interface library">YUI</acronym> Connection Manager</a>.</p>
<h3>Custom Events</h3>
<p>The interaction between the user interface and JavaScript is &#8220;event&#8221; based. Every time the user does something on the page, an event is fired. JavaScript allows us add function calls to each of these events, so that we can trigger some form of functionality.</p>
<p>Good examples of events would be &#8220;onmouseover&#8221;, &#8220;onclick&#8221;, and &#8220;onload&#8221; (although the latter is one of the few events that is <em>not</em> triggered by the user &#8212; rather, it is triggered as the page finishes loading).</p>
<p>For more information about JavaScript events, take a look at <a href="http://www.quirksmode.org/js/introevents.html">PPK&#8217;s excellent &#8220;Introduction to Events&#8221; article</a>.</p>
<p>&#8220;Custom&#8221; events are, in effect, an extension of this concept; except they&#8217;re defined by you, as an interface developer. Good examples of custom events might be &#8220;ontabchange&#8221; on a tab module, &#8220;onmenushow&#8221; or &#8220;onmenuhide&#8221; on a drop-down menu, or even stuff like &#8220;ondrag&#8221; when implementing drag/drop functionality.</p>
<p>In theory, you don&#8217;t even need any special code to do this; just some form of method call when the event happens &#8212; although, when you think about it, it would be much nicer to implement the <a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer design pattern</a> and allow another developer to &#8220;subscribe&#8221; to your event.</p>
<p>It&#8217;s exactly for this reason that the <acronym title="Yahoo! User Interface library">YUI</acronym> Event Utility allows the creation of custom events, and it&#8217;s that functionality that I&#8217;m going to use.</p>
<p>For more information on custom events, I&#8217;d recommend having a look at <a href="http://yuiblog.com/blog/2007/01/17/event-plan/">Christian Heilmann&#8217;s excellent <acronym title="Yahoo! User Interface library">YUI</acronym> Blog post, &#8220;Event-Driven Web Application Design&#8221;</a>. It&#8217;s also worth having a look at <a href="http://www.dustindiaz.com/custom-events">&#8220;Publishing Custom Events in JavaScript&#8221; by Dustin Diaz</a>.</p>
<h3>Mixing it all up</h3>
<p><a href="http://developer.yahoo.com/yui/connection/"><acronym title="Yahoo! User Interface library">YUI</acronym> Connection Manager</a> handles Ajax connections very well &#8212; but imagine we have a page containing a number of Ajax dependant widgets or <acronym title="User Interface">UI</acronym> components that ALL need to fire off their own asynchronous requests. Add to this the fact that we have a number of methods that may need to be run with the data returned from our request, and you have the potential for a lot of mutually exclusive connections that don&#8217;t necessarily need to be exclusive.</p>
<p>In this particular case, it would be better to create an object to handle all our Ajax requests; in much the same way that a dedicated <acronym title="Database Access Object">DAO</acronym> would handle database requests in any other object-oriented system. This object could then be used to manage requests and the methods to fire when those requests are successful.</p>
<p>To best achieve this, we wrap our <acronym title="Yahoo! User Interface library">YUI</acronym> Connection object and our <acronym title="Yahoo! User Interface library">YUI</acronym> Custom Event inside another instantiable (is that even the right word?) object &#8212; AjaxEvent.</p>
<h2>The Method</h2>
<h3>The AjaxEvent Object</h3>
<p>First things first, it&#8217;s important to make sure our code is namespaced. This basically stops us overwriting other code elsewhere, and encapsulates all our methods nicely.</p>
<p>For more about namespacing JavaScript, take a look at <a href="http://snook.ca/archives/javascript/javascript_name/">Jon Snook&#8217;s short post, &#8220;JavaScript Namespaces&#8221;</a>.</p>
<p>So basically, we need to check to see if a namespace object exists. If it does, we add our methods to that object, if not, we create a new object to add our methods to.</p>
<p>We do that like so:</p>
<pre><code>var NEF = window.NEF || {};</code></pre>
<p>Next we define our object in a way that allows us to instantiate it using the <code>new</code> operator. We do this simply so that we can have multiple AjaxEvents on our page that maintain their properties:</p>
<pre><code>NEF.AjaxEvent = function() {
  return this;
}</code></pre>
<p>Note that our object contains no members and simply returns itself on construction. This means that it will instantiate quickly and won&#8217;t slow down our scripts. We can use prototypal inheritance to add methods later.</p>
<p>Now let&#8217;s take a look at the methods we&#8217;re going to add. Firstly, there&#8217;s our <code>subscribe</code> method, which will allow us to subscribe methods to our object&#8217;s custom event:</p>
<pre><code>  /*
   * Subscribes a function or method to the custom event.
   *
   * @method subscribe
   * @param {Function}  fn          The function to execute
   * @param {Object}    oScope      An object to be passed as scope for the function
   */
  subscribe: function(fn, oScope) {
    if (!this.oEvent) {
      // Check to see if this.oEvent exists and if not, create it.
      this.oEvent = new YAHOO.util.CustomEvent("ajaxevent", this, false, YAHOO.util.CustomEvent.FLAT);
    }
    if (oScope) {
      // If oScope exists, we subscribe fn to this.oEvent, passing
      // oScope as it's scope object.
      this.oEvent.subscribe(fn, oScope, true);
    } else {
      // Otherwise, we simply subscribe fn to this.oEvent.
      this.oEvent.subscribe(fn);
    }
  }</code></pre>
<p>This is all fairly straight forward and simply creates our custom event (if it hasn&#8217;t been created already) as a member of our AjaxEvent. It then subscribes the function <code>fn</code> to it, using a scope object if one is passed.</p>
<p>Next we need to specify a method to perform our Ajax request:</p>
<pre><code>  /*
   * Performs an asynchronous request using the YUI Connection manager
   * and fires our custom event upon success.
   *
   * @method connect
   * @param {String}    sUri        Fully qualified path of resource
   */
  connect: function(sUri) {
    if (!sUri &#038;&#038; !this.sUri) {
      // If the sUri parameter has not been passed and the object's
      // sUri member has not been set then return false as we have
      // no where to make our Ajax call to.
      return false;
    } else {
      // Set up the object's sUri member to the most recent
      // location that's been passed.
      this.sUri = (!sUri) ? this.sUri : sUri;

      // We need to prevent Internet Explorer from caching our
      // Ajax request. To do this, we'll add the current date/time as
      // a unix timestamp onto the URI -- which will always be unique.
      // Firstly we obtain the current date/time as a unix timestamp
      this.dt = new Date().valueOf();

      // Next we work out how's best to add the number and add it.
      this.sUri = (this.sUri.indexOf("?") === -1) ? this.sUri + "?yaetime=" + this.dt : ((this.sUri.indexOf("yaetime") === -1) ? this.sUri + "&#038;yaetime=" + this.dt : this.sUri.replace(/yaetime=[0-9]+/i, "yaetime=" + this.dt));

      // Finally we fire off our asynchronous request using the YUI
      // connection manager.
      YAHOO.util.Connect.asyncRequest('GET', this.sUri, {
        success: function (o) {

          // Here we're making the assumption that our response
          // is JSON. We eval it...
          var oJSON = eval("(" + o.responseText + ")");

          // ... and then pass it to our subscribed functions
          // as a parameter (as long as it's valid).
          this.oEvent.fire((typeof oJSON === "object") ? oJSON : null);
        },
        scope: this
      });
    }
  }</code></pre>
<p>This method will ultimately return our <acronym title="JavaScript Object Notation">JSON</acronym> object as a parameter of the functions subscribed to our event. This means that we have instant access to any members of said object within that function.</p>
<h3>Implementation</h3>
<p>We implement our object like so:</p>
<pre><code>// To begin with, we instantiate our object.
var myAjaxEvent = new NEF.AjaxEvent();

// Next we subscribe a function to our object. I'm doing this
// anonymously here (as a lambda function), but there's no reason
// we couldn't pass it a function that had already been defined.
myAjaxEvent.subscribe(function (o) {
	// The parameter o is our returned JSON object on success of the Ajax.
	// As such, we can access its members just like any other object.
  alert(o.property);
});

// Finally, to fire off the Ajax request, we simply pass a fully qualified URI
// to the connect method...
myAjaxEvent.connect('gimmesomejson.php?skeleton=24');

// ...and should we wish to fetch that result again, we can call connect again
// without a parameter.
myAjaxEvent.connect();

// Should we want to change the URI, for whatever reason (eg. new HTTP GET), we
// can by simply passing a new URI.
myAjaxEvent.connect('gimmesomejson.php?skeleton=3');
</code></pre>
<p>So there you have it; a small script that manages and simplifies multiple Ajax calls. It&#8217;s not groundbreaking, but it&#8217;s certainly made life easier in our multi-developer environment.</p>
<h3>The Complete Script</h3>
<p>Finally, here&#8217;s the complete script (with the incidental comments removed):</p>
<pre><code>var NEF = window.NEF || {};

/*
 * The AjaxEvent class allows you to create DAOs for handling
 * Ajax requests. Upon request success, it fires a custom event
 * that handles subscribed functions.
 *
 * @namespace NEF
 * @class AjaxEvent
 * @constructor
 */
NEF.AjaxEvent = function() {
  return this;
}

NEF.AjaxEvent.prototype = {

  /*
   * Subscribes a function or method to the custom event.
   *
   * @method subscribe
   * @param {Function}  fn          The function to execute
   * @param {Object}    oScope      An object to be passed as scope for the function
   */
  subscribe: function(fn, oScope) {
    if (!this.oEvent) {
      this.oEvent = new YAHOO.util.CustomEvent("ajaxevent", this, false, YAHOO.util.CustomEvent.FLAT);
    }
    if (oScope) {
      this.oEvent.subscribe(fn, oScope, true);
    } else {
      this.oEvent.subscribe(fn);
    }
  },

  /*
   * Performs an asynchronous request using the YUI Connection manager
   * and fires our custom event upon success.
   *
   * @method connect
   * @param {String}    sUri        Fully qualified path of resource
   */
  connect: function(sUri) {
    if (!sUri &#038;&#038; !this.sUri) {
      return false;
    } else {
      this.sUri = (!sUri) ? this.sUri : sUri;
      this.dt = new Date().valueOf();
      this.sUri = (this.sUri.indexOf("?") === -1) ? this.sUri + "?yaetime=" + this.dt : ((this.sUri.indexOf("yaetime") === -1) ? this.sUri + "&#038;yaetime=" + this.dt : this.sUri.replace(/yaetime=[0-9]+/i, "yaetime=" + this.dt));
      YAHOO.util.Connect.asyncRequest('GET', this.sUri, {
        success: function (o) {
          var oJSON = eval("(" + o.responseText + ")");
          this.oEvent.fire((typeof oJSON === "object") ? oJSON : null);
        },
        scope: this
      });
    }
  }
}

/*
 * Example of Use
 */

var myAjaxEvent = new NEF.AjaxEvent();

myAjaxEvent.subscribe(function (o) {
  alert(o.property);
});

myAjaxEvent.connect('gimmesomejson.php?skeleton=24');
myAjaxEvent.connect();

myAjaxEvent.connect('gimmesomejson.php?skeleton=3');</code></pre>
<h2>Demo</h2>
<p>Here&#8217;s <a href="http://nefariousdesigns.co.uk/projects/ajaxevent-demo/">a nice demo of AjaxEvent in action</a>&hellip;</p>
<h2>Improvements</h2>
<p>The Ajax connection within my script is somewhat limiting; there&#8217;s really no reason why we couldn&#8217;t allow developers to specify an <acronym title="HyperText Transfer Protocol">HTTP</acronym> method, and to allow for POST variables.</p>
<p>I&#8217;m also assuming that the request returns <acronym title="JavaScript Object Notation">JSON</acronym> formatted data which, obviously, may not be the case in other environments. Once again, there&#8217;s no reason why we can&#8217;t allow the returned data to be manipulated <em>outside</em> the script; thus opening up any number of different opportunities.</p>
<p>Ultimately, in developing this script, we were simply trying to solve our <em>own</em> problems and didn&#8217;t really think about developing it further. Please feel free if you choose to do so &#8212; but please, let me know because I&#8217;d be interested in seeing the results!</p>
<h2>Credit where it&#8217;s due</h2>
<p>I really can&#8217;t claim sole credit for this script &#8212; the original idea was the brainchild of Yahoo! Europe JavaScript luminary Mark Aidan Thomas (who sadly shies away from maintaining any kind of online presence) &#8212; I just coded it, and then settled into script tennis; with a number of iterations going back and forth between us.</p>
<p>I&#8217;d also like to thank <a href="http://nodetraveller.com">Lawrence Carvalho</a> for being a great sounding board, a wealth of knowledge on the <acronym title="Yahoo! User Interface library">YUI</acronym>, and generally sticking his oar in where appropriate.</p>
<h2>Summary</h2>
<p>Hopefully this script will prove useful to someone else; after all, that <em>is</em> why I&#8217;m blogging it.</p>
<p>Once again, this script is only really useful if you page is absolutely loaded with Ajax requests. The page that facilitated the development of this script incorporated 7 different Ajax calls, each doing something slightly different and some requests repeating every 30 seconds. As you can well imagine, this would have been a coding nightmare without this script &#8212; even more so considering each Ajax call was being written by a different developer.</p>
<p>In the past I&#8217;ve been more comfortable using Prototype and Scriptaculous as my preferred JavaScript libraries. Unsurprisingly, since I moved to Yahoo!, the <a href="http://developer.yahoo.com/yui/"><acronym title="Yahoo! User Interface library">YUI</acronym></a> is now my weapon of choice &#8212; and to be honest, I&#8217;m really beginning to appreciate it. Without the functionality of the CustomEvent object and the Connection manager, the script above would have been a lot more complicated.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://nefariousdesigns.co.uk/archive/2007/07/ajaxevent-using-yui-custom-events-with-ajax/#comments" thr:count="6" />
		<link rel="replies" type="application/atom+xml" href="http://nefariousdesigns.co.uk/archive/2007/07/ajaxevent-using-yui-custom-events-with-ajax/feed/atom/" thr:count="6" />
		<thr:total>6</thr:total>
	<feedburner:origLink>http://nefariousdesigns.co.uk/archive/2007/07/ajaxevent-using-yui-custom-events-with-ajax/</feedburner:origLink></entry>
	</feed>
