Jul 02

Marathon Man

10:07pm on Saturday 2nd July, 2011

Throughout the period when we were considering and then waiting to relocate to Amsterdam, the possibility of getting more serious about keeping fit was at the back of my mind. And since we arrived (bar a single hangover break) I have been running every weekend, exploring the roads and parks within easy reach of our beautiful Vondelpark apartment. But, like so many of the activities I engage in, I’m starting to feel the need for a tangible goal—and, since running doesn’t award online badges or make me mayor of imaginary places, I may actually need to declare a real and tangible endgame for this habit.

So I’ve decided to run the Amsterdam Marathon, which is conveniently happening right outside our front door in October. That gives me three-and-a-half months in which to train, learn about proper nutrition and increase my weekly distance to a suitably imposing number. I’m pretty confident that, barring injury or illness, I’ll be able to complete the full distance somewhere south of four hours.

Training & Tracking

The largely flat surroundings of Amsterdam make training pretty stress-free, and as a non-native there are enough new sights and sounds to keep my attention occupied while I pile on the miles. I started out considering a linear growth in my mileage per week, but subsequent research online seems to indicate that most marathon training programmes top out at about 20 miles in one go, with a weekly maximum growing to around 40 miles before tapering off in the final few weeks to give your body time to recover for the big day. I’m managing about 8-10 miles per week at the moment, running at the weekend and once during the week, so it’s likely I’ll need to add an extra weekly session to build up to a realistic mileage.

There are many different ways to track your progress and development, both online and mobile. DailyMile, RunKeeper, Nike+, EndoMondo and others all offer fancy graphs, charts and incentives to monitor and manage your athletic endeavours. I’ve been using RunKeeper for quite a while, but after having a play with DailyMile recently I find I like their route mapping much more, with its auto-snapping to roads and Web 2.0-style design. Sadly none of the sites I looked at offered pointless badges to unlock, but no doubt I’ll be sharing various sessions on Facebook anyway.

De juiste kleding

I’ve heard it said that the Dutch claim a connection to the equally long-of-limb Masai, and perhaps that might explain their need to wrap up warmly even in the most balmy conditions. Typically I tend to wear a random tech conference t-shirt and some old shorts to run, but it’s not uncommon that I find myself passing fellow runners decked out in full tracksuit, in wooly hats even. It’s a similar story during the week—I ride to work in a t-shirt; they are in coats and sweaters. At any rate, now I’ve signed up for the marathon I felt I should splash out on some decent running gear; tomorrow I’ll be sporting my brand new bright orange breathable shirt and some barely decently short shorts.

Wish me luck

So now I’m signed up and kitted out with reasonably serious-looking gear, I feel comfortable announcing this rather intimidating life goal. Wish me luck.

May 15

No more CSS hacks: Browser sniffing with .htaccess

9:40pm on Sunday 15th May, 2011

Ask any web developer what the worst part of their job is, and chances are that browser testing will feature pretty high in the list. Ever since we ditched HTML tables and started using CSS to lay out our web pages, it has been a constant struggle to make designs look the same in every browser.

Of course, for the biggest headache Internet Explorer there has always been the blessing of Conditional Comments. These specially crafted comment-like tags let us specify IE-specific styles or stylesheets, safe in the knowledge that they will only be recognised and downloaded by the targeted browser(s). And if it was only IE that tripped us up, that would be fine. But inevitably once you start building bigger and more complex designs, you are going to run across niggling little inconsistencies in one browser or another where Conditional Comments can’t help you out.

Previously the only way to deliver different CSS rules for browsers was to rely on a complicated set of ‘hacks’—either parsing bugs or unsupported CSS3 declarations that allowed some rules to be ignored by some browsers. But it’s not easy to remember every convoluted hack, and when you’re up against a deadline and Opera 9 doesn’t render quite the same as Opera 10 you have better things to do than Google for that specific fix.

Luckily, there is an easier way to detect browsers and their versions.

Special (User) Agent

When any browser requests a web page from your server, it sends a bunch of request headers. One of those headers tells the web server what the browser is called: the User-Agent string. There are approximately a gazillion of these strings—have a look at Zytrax.com’s list if you’re interested in learning some of the more bizarre options—but for the purposes of modern web development we’re really only interested in the most commonly used browsers:

  • Microsoft Internet Explorer
  • Firefox
  • Safari
  • Opera
  • Google Chrome

Unless you’re writing a site specifically for obscure Linux distros, these five browsers will probably make up 99% or more of your visitors. Each browser manufacturer uses a slightly different string—some even include other browser’s names in their user-agent—but they (generally) tend to follow a predictable pattern. And that means we can recognise and extract them using regular expressions.

Regular expressions and .htaccess

If you’re used to running on Apache you probably have some experience with the .htaccess file. It is used to control access to files and folders, redirect requests, and provide various server-level bits of information back to the browser. But it can also be used to create additional environment variables that you can use in your web pages.

What we’re going to do is interrogate the User-Agent string for our five browsers, and extract the browser name and version numberfor use in our pages. First, add these lines to your .htaccess file:

What we’re doing here is using a regular expression to look for the browser name, followed by a space or a forward-slash, and then a number. The order of browser names is important here, as Chrome’s User-Agent string includes “Safari” (and Camino includes “Firefox,” if you want to add that browser into the mix). You might also notice that Safari is missing; in its place is a mysterious browser called “Version.” That’s due to how Safari UA strings are constructed; they use a build number at the end instead of a version number, with the version number earlier in the string. Using regular expression backreferences we assign the first matched expression to the variable ‘browser’ and the second match (a single number) to the variable ‘version.’ The second line accommodates Safari’s difference by checking for the not-really-a-browser “Version” and replacing it with the correct name. And finally we trim Internet Explorer’s name down to the more familiar “IE.”

So now we have grabbed a couple of useful bits of information out of the User-Agent string of the user’s browser—what can we do with them?

Environment variables in PHP

Any variables created in this way are added to PHP’s superglobal array $_ENV. Just like the $_GET and $_POST arrays, you can output the values by referring to the array key:

<p>You are using <?php echo $_ENV['browser']; ?>,
  version <?php echo $_ENV['version']; ?></p>

Environment variables also have a second access method, the getenv() function. Simply pass the variable name in the function call to retrieve the value:

<p>You are using <?php echo getenv('browser'); ?>,
  version <?php echo getenv('version'); ?></p>

Very nice, but how can we use this information instead of CSS hacks? Simple; we just add the browser and version to the class of the <html> element:

<html class="<?php echo getenv('browser') . getenv('version'); ?>”>

This technique allows you to write browser-specific rules that override the base declaration by including the browser-specific class name:

#mydiv {
  position: fixed;
.IE6 #mydiv {
  position: absolute;

Arguably this approach makes more sense than conditional comments, as it means that targeted browsers aren’t required to download an additional file, but you should probably look at your site stats to see whether your Internet Explorer traffic is high enough to make up for other browsers taking the hit of downloading unused styles.

Adding classes to the <html> element is not valid HTML in HTML4 or XHTML1, but it is valid in HTML5. Tools like Modernizr have adopted this technique when augmenting markup, and I think it is a sensible place to put these new classes (particularly as IE6 has problems with multiple classes in declarations, so putting them on the <body> might have unforeseen consequences).

But I’m not allowed to edit my .htaccess!

As it’s a simple regular expression, the functionality here can be duplicated in PHP alone very simply. Just place this code before the start of markup (or in a global include file if you’re using a CMS):

Then simply refer to those new variables instead of the environment vars:

<html class="<?php echo $browser . $version; ?>">


“Hang on just a gosh-darned minute,” I hear you say, “Browser sniffing is bad!”

Well, yes it is, in the context of late ‘90s JavaScript, but I’m of the opinion that pragmatism trumps idealism. In a perfect world, every line of CSS we write would be a well planned part of an overall framework, and every element on the page would be carefully constructed to avoid any possible browser inconsistencies, but anyone working on the web today knows that is rarely the case. Budgets and timeframes aren’t designed to accommodate more than a cursory glance at older browsers, and sometimes a quick fix is all that is needed; it’s in these cases that being able to target a specific combination of browser and version comes in very handy.

That said, I would not advocate using this technique to target the most up-to-date versions of modern browsers. If you’re having to hack the current version of a browser then you’ve done something wrong, and run the risk of that same thing breaking as soon as Firefox 5 or IE10 is released. Far better to ‘fix’ older, static versions of browsers—Internet Explorer 7 and below, Opera 9 and lower, Firefox 3 and so on—as you know they are not going to change their behaviour.

Example page

Here’s an example page showing the technique in action. Note that it could also be extended to detect the platform (Windows or Mac) of the user as well, in case you want to get even more specific. You might want to make use of this technique to show or hide the right buttons to download software, for example, by writing something like this:

.download-win, .download-mac {
	display: block;
.Mac .download-win, .Win .download-mac {
	display: none;

Note that, depending on the policy of your webhost, you might have to follow certain restrictions when it comes to naming your new environment variables. For example, MediaTemple insists that any variables created in this way must start with “HTTP_”.

If you have any more suggestions for how to extend or improve the idea, let me know in the comments.

May 14

Future of Web Design 2011

10:27pm on Saturday 14th May, 2011

It’s been a while, but next week I’ll be returning to the British web design conference scene when I attend the Future of Web Design (FOWD) conference in London. It’s a two day, dual-track format with plenty of essential sessions covering the latest and greatest web design and development techniques.

Unfortunately I don’t yet know how many of the talks I’ll be able to attend—I’ll be there manning the recruitment stand for Booking.com, handing out our free schwag and hoping to talk to anyone interested in working for one of the most interesting ecommerce websites around. But in between work chat there are definitely a few sessions that I hope I can see.

Day One

Opening Day 1, Aarron Walter of MailChimp presents ‘Transforming Ideas Into Interfaces.’ Aarron’s book, Building Findable Websites, might be a few years old now but it’s still a great primer (or reminder for old hands) of the right way to do things. As UX design lead at MailChimp he is responsible for one of those ubiquitous UX examples that have been cropping up on user psychology slides in the last year: the MailChimp mascot forms part of the header of the site, and gives helpful or humorous advice—or loses his arm if your browser window is opened too wide! Right after Aarron, Carsonified’s Mike Kus talks about ‘Designing for Humans.’ The description of this session is a little vague, but my hope is that it touches at least a little on user psychology and the effect of design decisions on emotional state.

As I have no interest in hearing about WordPress (and really, is that the “future” of web design?) I think the other morning session is worth your time. Rachel Andrew has been writing and speaking about this stuff for longer than most, and if you’re going to work as a designer it really does benefit you to also understand the basic concepts of development. (I actually had a vague idea for a book on this topic, something like “PHP Development for Web Designers” that would cover how to achieve basic tasks with the minimum of programming experience, but as per usual life got in the way.)

At the end of the first day it seems to be de rigeur for the final speaker to step back from practicalities and focus instead of more abstract ideas; it sounds as if Aral Balkan’s ‘Making The New Everyday Things’ talk will fit that bill.

Day Two

On Day Two, there is an interesting talk by (relative) newcomer Femi Adesina on handling creative block and ‘Enhancing Your Creativity.’ It’s something I’ve always struggled with; although I’m a classic hybrid designer-developer, I find it much easier to churn out a few hours’ code than to spend the same amount of time in Photoshop. I hope this session provides something a little more imaginative than recommending we “go for a walk” or “read a non-design magazine.”

After a mobile-heavy morning in both tracks, John McGarvey presents ‘Copywriting is Design,’ one of 2011’s hot topics for design minds, and something that is easy to overlook in your average design department. At Booking we’re lucky to have on-site copywriters working in the same team as the designers and developers, so content design becomes an integral part of all our projects.

Young Mr Stocks takes to the stage once more to educate the masses on the right time and wrong time to break out that advanced HTML5 and CSS3 bling—it’s not the most inspired session title, but anytime I see Elliot’s name and “solid design principles” in the same sentence you know there’s going to be something good to take away.

The final two talks of the conference interest me for different reasons. Sarah Nelson’s ‘Bullet Proof Communication Techniques: A UX Strategist’s Guide’ takes an interesting direction for a web design conference by tackling the question of effective communication by designers. The wording of the summary seems to want to set up the assumption that designers and UX people are traditionally excluded from decision-making (not the case where I am), but it will be interesting to see how the recommendations fit with our own approach to designer empowerment.

Rounding out the day is Mr Hot Topic 2011. Ethan Marcotte has contrived to be the poster-boy for responsive design this year, so it’s unsurprising that FOWD have chosen to end on that note—I’m somewhat concerned that it is becoming just another buzzword and technique employed by designers without any thought or consideration for their own unique situation or context. We will see what spin Ethan puts on things.

The FOWD iPhone app

I also installed the FOWD iPhone app to see whether it could add anything to the overall conference experience. I was expecting quite a clunky interface considering the app is powered by a white-label provider (MobileRoadie are “a turn-key platform to quickly and inexpensively build mobile apps” apparently), but it’s actually quite pleasant to use (although they should really fix that “London 2010” splash page).

The News panel pulls in tweets tagged with the #FOWD hashtag or @FOWD account name, and is augmented with “Buzz” which seems to be content related to the speakers or sessions. The full schedule for workshops and talks is included (although rather misleadingly entitled “Shows”), with the ability to comment, or add yourself as an attendee, Gowalla-style, for each session. You can connect with either Facebook or Twitter, and the app also provides Facebook or Foursquare geo-checkin integration too, presumably for use during the actual conference.

The Speakers pages, aside from a nice Coverflow faceboard, seem to just replicate the content of the FOWD website, plus the ability to leave comments (hopefully moderated) on individual speakers’ profiles. There is also an Attendees list, presented in the standard iPhone A-Z style; I’m not quite sure how it is populated though—I’m not on it, so it’s not drawn from the actual attendee list, but the number of people in the directory seems too high for them all to be registered users of the app. Clicking on attendee names also does nothing. I tried signing into the app with my Twitter account, which gave me a profile area and some kind of points system, but I still couldn’t figure out how to interact directly with other attendees. Perhaps all will become clear on Tuesday.

Overall it seems like a nice idea and a handy way to augment the backchannel chatter—that is, assuming the wifi stays up for the duration.

Gis a job

As I said earlier, my main reason for being there (and the people paying my bills) is Booking.com, where we are recruiting for web developers and designers, as well as some more specialised positions in SEO, consumer psychology, ecommerce conversion and some mobile stuff. We have a booth right next door to Clock and Microsoft in the main hall, so swing by if you have a burning desire for a free energy drink, custom lanyard, or a selection of branded stationery. I think we also have some iPad/MacBook screen protector/cleaning cloths too, if you’re the grubby-fingered type.

I’ve worked for Booking for several years now, first in Cambridge and, since April this year, at the head office in Amsterdam, and it’s far and away the best job I’ve ever had. The amount of personal responsibility you are given right from the very start is daunting, especially when you realise the scale of the revenue that you are dealing with, but the flat management structure and freedom to fail coupled with a team of brilliant individuals all pulling in the same direction makes each day exciting. Our working practices are different to almost anywhere else you might have worked; user focus is taken to another level, and you can see the effect your own work is having on actual users from Day 1.

So if you’re considering a change of scene, and Amsterdam appeals to you, come and talk to us about our current vacancies. We’re fully prepared to sit down for an impromptu interview if we think you’ve got the right stuff, and we’ll fly you out to visit us in the ‘Dam (including hotel accommodation) for a proper interview too. For an unbiased look at what it’s like to apply for a job with Booking.com, you should read Stuart Frisby’s account of his application and interview process (and Stuart now works alongside me in the Frontend Team).

See you there!

I’m looking forward to meeting up with a few old internet friends this week, and hope to meet even more new people at the booth. If you’re going to be at FOWD, come and say hello—and if you or someone you know is thinking about a career change, be sure to send them my way. :)

May 10

Five weeks down in Old Amsterdam

12:08am on Tuesday 10th May, 2011

One month into our grand Amsterdam adventure, one Queen’s Day down, and daily life seems to have found its own pace. We still contrive to get lost occasionally (although last time it was definitely the Metro’s fault, not mine), and estimating just how much shopping is going to weigh too much to easily carry up three flights of stairs is an ongoing experiment, but a comfortable routine is beginning to emerge.

Location, location, location

Commuting to work has changed from an hour by train and foot into a pleasant fifteen-minute bike ride through the currently flowering Vondelpark. Before we moved, several people had told us that Amsterdam was less a city and more like an oversized village, and our proximity to the centre of the city (ten minutes by tram) means that it feels like an easy jaunt to the shops rather than a daunting trek into the heart of a big city. Sure, more public toilets would be nice when out and about with three little girls, but you can’t have everything. Like so much of Amsterdam we have an Albert Heijn supermarket just a few minutes up the road which has provided the bulk of our food and drink so far. We’ve also discovered other Dutch favourites like Blokker, HEMA and Dirk, all within walking distance. Lacking a car does have the tendency to encourage you to shop locally, when you’re relying on muscle power alone to get the shopping home.

One big benefit of our new apartment’s location is the Vondeltuin playground and bar, mere seconds from our front door. We obviously lost our garden in moving to an apartment, so for the children a large sandpit and climbing frames right outside makes up for that a little. The attached bar and cafe seems a little pricey, but you can’t beat sitting in the sun with a beer or glass of wine, watching your children having fun. (Shockingly it partly burned down a few weeks ago, on an evening when we almost decided to go down there. Nobody was hurt, and they managed to re-open in time for Queen’s Day a few days later.)

Our local area also seems to be awash with kindergartens; apart from the one directly below our apartment, there are two or three more within a couple of minutes walk. The Dutch style for nurseries seems to include large picture windows looking out onto the street, so we walk to school every morning under the watchful gaze of the local three-year-olds.

Coming from a Fen village that is lucky to see one bus a day, the overwhelming public transport presence in Amsterdam is an enormous change to deal with. Trams and buses pass by every few minutes, and the stops are always equipped with up-to-date and easy to comprehend timetables. Of course, there have been some difficulties: it has taken a few weeks for the kids to learn to find something to hold on to as soon as they board a tram (tram drivers are not particularly sympathetic to passengers’ preference for remaining vertical), and avoiding bike lanes sometimes requires rather more shouting than strictly necessary. (When moving to a city of half-a-million bicycles it seemed sensible to bring our own bikes out here with us, and I’ve been riding to work since my second day. You do sometimes feel like the only mountain biker in a city where everyone rides upright, wrought-iron boneshakers, but at least it gives you the edge away from the lights.)

Hooked up

Other than a Dutch SIM card for my iPhone we are now fully set up with local services. ABN AMRO is the only Dutch bank to offer an English-language internet banking interface, so that was an easy decision, but they’ve been very good so far and I’m impressed with both their correspondence and the features of the internet banking service. I was warned that, despite receiving a credit card as part of our ‘pakket,’ I should not expect to be able to use it in the same way as my UK credit cards; apparently full payment is required regularly, making it more of a postponed debit card than anything else.

Our telecoms are provided by UPC, and these too were fairly easy to setup and configure. We’ve gone from the bare minimum of Freeview channels and a 1.5meg rural internet connection, to something approaching 100 channels and 25meg cable, including BBCs 1, 2, 3 and 4 and several music and film channels. The kids are missing CBBC and CITV, and can’t yet convince themselves that watching cartoons in Dutch is entertainment rather than learning.

(One tip for anyone considering moving abroad: get your passport renewed before you leave the country. My passport ran out at the start of May, so I sent it away… to France for some reason, as the British consulate in Amsterdam doesn’t do passport renewals any more. It remains to be seen whether it returns in time for me to attend the FOWD conference in a couple of weeks.)

Back to school

The kids got off to a running start with their schooling here in Holland. Their new school is a five-minute walk down the road, and they have all quickly made new best friends (so important when you’re seven years old). The school is a mainstream Dutch primary school, although being an inner-city school only around 50% of the pupils are native Dutch; the rest are a mixture of ex-pat kids and immigrants from the ex-colonies; in the girls’ classes they have become friends with several Brazilian girls due to their reasonably good English. It’s been harder for us to meet other parents, though—opening directly onto the road means that the school lacks a convenient external playground area for parents to congregate and interact.

Of course, the highlight of their education experience so far has to be the fact that they have learned how to swing round hanging bars by hooking their legs around them. From the first day here we noticed all the little girls spinning round and round, heads inches from the ground, and it didn’t take our three long to pick up the technique—they’ll definitely have something impressive to show their friends back home next time they see them!

Queen’s Day

We were lucky enough to end up moving a few weeks before The Netherlands’ biggest celebration: Queen’s Day. Shops filled up with orange crap to wear or drink—our girls all sported orange cowboy hats on the day—and Amsterdam was transformed into the world’s largest car-boot sale on a beautiful sunny Saturday at the end of April.

Our own Queen’s Day was fairly low-key. With three (relatively) small children in tow, we didn’t fancy braving the excesses of the main tourist areas in the city centre, so we restricted ourselves to a couple of circuits of Vondelpark, which is given over to children trying to bolster their pocket money by selling off their old toys and clothes or busking for spare change. By 10am the pathways were jammed with shuffling people winding between blankets festooned with junk; we eventually allowed the kids to spend a few euros on cast-offs and escaped through a side exit. After some beer and bitterballen at the cafe on the corner, we returned home and watched the rest of the day from the balcony.

Settling in

Despite now entering our sixth week in Amsterdam, I don’t fully feel like a part of the city yet; thus far the amazing weather and our relaxed schedule have contrived to make it feel more like an extended holiday than a new permanent home. The exception has been the one Sunday afternoon when I opted to run in the afternoon instead of the early morning. Jogging through a Vondelpark in full tourist swing—avoiding the bikes, slow-moving police cars, wandering tourists, ice cream vans and other runners; running through the alternating clouds of barbeque and marijuana smoke—I really felt like a part of the life of the park. Not a tourist, there to enjoy the sunshine before moving on to the next European capital. I live here, and I have things to do.

Apr 25

Clean machine

5:33pm on Monday 25th April, 2011

It is gospel in the web development biz that a new job means a new laptop, and I spent a happy hour or two downloading and configuring software on my shiny new MacBook Pro this week. Part-way through the process, I realised just how heavily skewed towards productivity my choices have become.

There are some apps I need to work

Of course there is a bare minimum of necessary software that I can’t work without; as a web designer, that means somewhere to code web pages and browsers to look at them.

  • Aptana Studio: I started using Aptana when it was first released, and I’ve stuck with it ever since. The Eclipse-based plugin architecture was useful when I was writing PHP, and I still find its Project Explorer, colour coding and validation extremely helpful.
  • Firefox, Chrome: With Safari already installed, all I need to install is Firefox (and Firebug) and Chrome. I hardly ever test in Opera any more (a combination of lack of users, and confidence in its rendering engine generally getting things right).
  • Adium: For intra-team/office communication over Jabber.
  • MacFusion: We develop on remote servers, so I need a means to mount those drives as local for working on.
  • MS Office: Bloated and horrible but necessary in a modern office. I tried relying on NeoOffice for a while, but it occasionally does funny things to people’s CVs so I switched back to Microsoft.
  • Remote Desktop Connection: No Parallels, so IE testing is performed via remote desktop. RDC now comes bundled with Office 11.

There are some apps I need to help me work

So that is what I need to actually get work done, but there are many little apps to truly make me productive.

  • Alfred: I loved QuickSilver, but it occasionally didn’t do what I expected and was much more complex than I had need of. So when an old friend launched her first app, I happily switched over and have been very happy with how Alfred performs.
  • Caffeine: Saving countless hours of nudging the mouse when the screen goes off during meetings…
  • Dropbox: I mostly find the cloud-sharing app Dropbox useful for throwing files in that I need to access from home or mobile, but it also came in handy when migrating between laptops; all my bookmarks, useful settings, bash profiles and the like made their way over to the new machine via the magic of Dropbox.
  • Fluid: I run my daily task app and system monitoring tools as standalone apps in Fluid.
  • Jumpcut: Being able to recall the last forty pieces of text from my copy+paste clipboard has had an enormous effect on my work speed, more than you might expect; Jumpcut was the first clipboard management app I found and I’ve been happy with it for years.
  • Visor: It’s not to everyone’s taste (especially anyone trying to work on my machine) but I much prefer to have Terminal accessible from any app or any Space on my Mac; this handy little app turns it into a pop-down console window akin to FPS game interfaces.
  • Wunderlist: It’s not perfect, but Wunderlist with its free native Mac, iPad and iPhone app versions is performing pretty well as my GTD/task management setup for the time being.

And there are some apps that make work bearable

For me, no clean install would be complete without some music-related bits and pieces, and of course a drip-feed from the social network du jour.

  • Last.fm: Online radio and iTunes scrobbling to my Last.fm profile.
  • Spotify: Free (although soon to be heavily restricted) music; there’s not much they don’t have.
  • Twitterific: I managed to kill Twitterific a few months ago on the old laptop, so it’s nice to have it back again. I tried the new Twitter app and couldn’t get on with it, and I’m still not sure I completely like the new version of Twitterific either since I can’t work out how to make it appear each time a new tweet is posted, but for now it will do.

And finally

One last tweak was necessary to finalise the new machine setup: replacing the default Mail.app icon with a UK version of the iconic stamp! I’m about as far from a royalist as you can get, but there’s something altogether wrong about a postage stamp without Her Maj on.

And that’s about it. You might have noticed that I’m missing a graphical app; I’ve always used Photoshop, but I’m debating whether to take this opportunity to switch to Fireworks. And no doubt I’ll end up with a few dozen scarcely used programs over the coming years, but for now these are my ‘clean machine’ go-to applications. If you have any suggestions or want to point out a glaring omission, comments are open.

Mar 30

Ideas of March

7:01pm on Wednesday 30th March, 2011

“We need a blog revival.” So says Chris Shiflett, web security expert and one of the Analog co-op, in his post Ideas of March—and he’s not the only one. His call for a move away from our modern ADD Twitter habits and a return to our online beginnings as blogroll afficianados seems to have struck a chord with ex-bloggers around the world, and several thousand posts have appeared in the last few weeks announcing their owners’ intentions to resurrect their personal blog wasteland throughout March.

As you might have guessed from the surprise lurch into activity here, I am announcing my intention to join Chris and everyone else in blogging more, not just in March (for I seem to have joined that particular bandwagon a little too late) but in general.

Second time lucky

Of course, there was an attempt at a blog revival last year when Anton Peck announced Project 52, an initiative that asked participants to sign-up and declare their intention to publish at least one blog post for every week of the year. While it gained traction at the start of 2010, signing up over 600 people—I even signed up myself, managing, um, six weekly entries—it unfortunately faltered after the first couple of months, ‘rebooted’ in March, and then went quiet until the 2011 challenge was announced back in December. This year there seem to be only around forty participants and a mere 100 entries so far, suggesting that while setting a schedule might seem like a sensible piece of motivation, in practice it’s extremely tough to stick to and can easily become just another pressure on your conscience.

Aside from the ease with which thoughts can be shared on Twitter and never make it any further, the biggest factor in my own lack of activity has been work. Although I don’t do a lot of freelance development work, I like to keep my hand in on the PHP front, and so I had a fairly steady stream of work in 2010. The end result was a combination of no time in which to blog, and no energy with which to do it. Add to that the pressure of our impending relocation to Amsterdam and unhappiness with this current design, and it’s hardly surprising that I haven’t posted anything of note since August.

But since the beginning of the year, things have changed.


We gave up trying to sell our house and instead went down the rental route, which has the dual benefit of being faster and leaving us with a base in the UK to which to return should things not go as expected in The Netherlands. And I officially closed the door on my freelance business, offloading hosting clients to other local freelancers and declining every offer of work since the start of 2011.

The final step in our major life change takes place later this week, when we hand the keys over to our rental agent and board a plane headed for Amsterdam and our new life as bicycle-riding, apartment-living, city-dwelling Europeans. It’s a change that will mean less commuting for me, and less weekend work for my wife—and therefore a substantial increase in the amount of quality, family time we can spend together with the children as we get to know our new home.

One of the uses to which I plan to put this new free time is more blogging; both in the traditional ‘work’ areas—HTML, CSS, JavaScript, PHP and the web—but also on more personal topics as a means of bridging the increased distance from family and friends (and no doubt this will include plenty of introspection on the subject of Brits in Holland.) The intention is also to get out of the habit of hitting Publish before I am ready, instead taking the time to really craft a well-written, carefully researched article or tutorial. Since this idea of a blog reboot and revived writing schedule has been bouncing around my mind for a while, I have revisited my neglected Evernote account and started collecting ideas and plans in earnest.

Aside from writing more, I think the move to Amsterdam and the need to share how the children are growing up might be the push I finally need to purchase a Flickr Pro account (or alternative photo host, since Yahoo! don’t necessarily seem to be the most trustworthy of online guardians for my personal data) and start taking and posting more regular photography.

Redesign itch

When I redesigned and relaunched this site in 2009, it included some cURL and XML cleverness to retrieve various parts of me from around the internet—what I was currently reading, listening to, watching or bookmarking—and insert them into my database for display in the site footer. There are a few obvious drawbacks to this approach: you’re reliant on (several) third-party services for keeping your own site up-to-date, and at the mercy of their APIs; and you also end up with all that data duplicated in two different locations.

So, while I still like the idea of pulling in a lifestream, I think for the next iteration of the site I will turn to something like ThinkUp, which mitigates against both of the issues mentioned above while also giving me a bunch of useful tools for manipulating and displaying all of that data.

For the last six months or thereabouts I have been considering redesigning, and my Evernote “Notebook” is filling up with a combination of design inspiration/planning (currently I’m heading down the online newspaper route, responsive design and all) and notes on potential technology choices (I still haven’t decided whether to abandon the fairly expensive ExpressionEngine, and if I do, whether to use an alternative blog platform or just roll my own). The current design is also a factor in the lack of content; when you’re not happy with how an article will look when published, it’s hard to work up the motivation to write it at all.

Tearing it down and starting from scratch is also an option (cf. Andy Budd’s new undesigned but happily reactivated blog, one of the very first I read when I became interested in web design), although I suspect that would niggle at me just as much as the current design. Perhaps I will receive a burst of inspiration from our new Dutch surroundings and design something with tulips and steep staircases, who knows.

Finally, as a commitment to myself, I have also purchased a license for Scrivener, one of the most popular writing tools available for the Mac. Writing this post I’m finding that it really fits with my way of thinking, allowing me to capture random thoughts and bits of sentences, write short pieces independently of each other, and then re-order the article into the right sequence.


So, that’s a summary of my intentions, and I sincerely hope that this year I manage to live up to them. If you, dear reader, feel similarly motivated to reawaken your own blog, here are some simple instructions lifted from Chris Shiflett’s original post:

  • Write a post called Ideas of March.
  • List some of the reasons you like blogs.
  • Pledge to blog more the rest of the month.
  • Share your thoughts on Twitter with the #ideasofmarch hashtag.

Looking at that list now, I realise that I have neglected to list my own reasons for preferring blogs to the new breed of lifestream-enabling apps and sites like Twitter, Facebook, Gowalla and the like. Aside from the reasons listed by Chris, Drew and others, I can add:

  • More people blogging would rid my Twitter feed of the multi-tweet rant to which some people seem to be prone. Any time you feel yourself considering how best to explain yourself over a series of tweets, you really should write a blog post instead and link to it; create something permanent and searchable and facilitate archived conversation.
  • I want to be a better writer—and, like any skill, the only way to improve it is to keep doing it. Twitter is pretty much the exact opposite of encouragement to write more.

So, there it is—my declaration of intent: blog more, not just in March but as an ongoing habit.

Aug 21

How to fix the broken iPad form label click issue

2:33am on Saturday 21st August, 2010

I love my iPad. It’s almost perfect. If only I could click on form labels! Here is how I fixed that particular niggle with some judicious use of of JavaScript.

Updated 23/08: Created a jQuery version - see the bottom of this article for the code!

If, like me, you love some semantic HTML markup, it’s likely that your form elements—input, select, textarea—are marked up something like this:

<label for="your_name">Your name:</label>
<input type="text" id="your_name" name="your_name" 
  size="20" maxlength="20">

You might wrap the input inside the label, but the result is the same—clicking on the label will give focus to the text field so you can start typing (or select/check it in the case of radio buttons and checkboxes). If you’re particularly clever you might even be able to string together a relatively coherent sentence involving Fitt’s Law—but all that falls apart when it comes to Mobile Safari.

Labels in Mobile Safari

Mobile Safari, the browser found on iPhones, iPod Touches and the iPad, does not (currently) implement the same label behaviour as other browsers. Clicking on labels doesn’t do anything—possibly, as Ben Darlow suggests, it is because it would interfere with the tap-to-select-text functionality, although personally I think that usability trumps obscure text-selection use cases.

What’s even weirder is that, in over an hour of googling, I couldn’t find a single reference to this issue. Surely someone, somewhere must have noticed that clicking or tapping on labels in forms on iPad doesn’t select the input? I resolved that when I published a fix for the issue, it would include a couple of clunky sentences stuffed with as many keywords related to the tap click form label input select checkbox radio button problem as possible…

Enable iPad or iPhone users to activate your form elements when they tap on a label

Here is a simple script that does just that.

Very simply, it collects all the labels on the page, then loops through them and applies an onclick event (which the iPad triggers when you tap on an element). The event looks for a for attribute, figures out what sort of form element it relates to, and performs the correct action; either focusing on the element (text inputs, dropdowns and textareas) or toggling the selected state of checkboxes and radio buttons.

There is a test page here where you can try the script on your own iPhone or iPad. If you have an alternative method, or more efficient way to code it, please let me know in the comments. If someone wants to knock up a jQuery plugin as well, that would be nice, as I’ve forgotten how to do it…

As we only need to call the function for the affected platforms, just do something like this (using your document.ready event of choice):

if (navigator.userAgent.match(/iPhone/i) || 
  navigator.userAgent.match(/iPod/i) || 
  navigator.userAgent.match(/iPad/i)) {

(And don’t forget that, if and when Apple fix this “bug”, to remove the script.)


And here’s a version of the code in jQuery instead - obviously you need to have the library loaded in your page as well.

Original photo by Phantomfies

Mar 25

Bill Nighy makes a mean cocktail

6:18pm on Thursday 25th March, 2010

I’d been looking forward to the movie for at least thirty seconds, although now I can’t even remember its name. A tired sequel to a Disney franchise, I think; anthropomorphic animals and plants, singing and dancing. Don’t ask me why we wanted to see it. The cinema was actually inside the hotel where she worked, and I was hoping we could make it from the restaurant over to the cinema with enough time to catch the Pepsi adverts.

In the restaurant—upscale dining, large round tables, food that you know is too expensive but feels like a treat to order—I caught her arm. We had to go.

“One more order then I’m ready.”

I followed her over to the bar area, dodging the other staff as they swirled and eddied around the tables, almost falling over the girl crouched at the top of the small flight of stairs cleaning cutlery. I leaned against the smooth top of the bar and watched her as she filled her tray; two coffees and a dark, bitter-looking cocktail.

“I’ll take that for you,” said another anonymous waitresses, leaning across the bar, hand extended to claim and balance the laden tray.

“Thanks,” she said. Dropping her apron in a drawer, she took my hand. “Let’s go!”

Through the restaurant entrance hall, we pushed through the heavy double doors and out into the hotel reception area.

“Just a second,” I said, “there’s something I need to do.”

Cutting diagonally across the broad carpeted floor I entered the small hotel bar. It was empty save for the occupants of the only two stools at the counter; a midget wearing a gold lamé suit, and BAFTA award-winning actor Bill Nighy. Turning to regard me, Nighy slowly rose and moved behind the bar.

“Drink?” he asked, placing a whisky in front of me. I sipped it quickly as the pair watched me. The dwarf hopped down from his stool and moved towards the door.

“Another.” insisted Nighy; this time a shot glass of tequila appeared on the bar.

“No, I’m afraid I really have to go,” I protested. The dwarf stood aside as I left the bar, but turning back I bent down to bring myself level with his ear. “Can you tell me where the toilets are?”

Raising one arm he indicated a door further down the corridor. “Thanks,” I said. Sweet relief.

As I pushed hard on the heavy swing door, I woke up. Perhaps unsurprisingly, I really needed to pee.

Mar 19

Write PHP Properly

10:59pm on Friday 19th March, 2010

For your reading pleasure this week, I bring you two cautionary tales on the importance of not taking shortcuts in your PHP code, or making assumptions about your (future) hosting environment.

Short tags off

For years I’ve been using PHP’s short tags to write out variables within HTML. For this habit I at least partially blame the CodeIgniter documentation, which uses short tags liberally to illustrate how to output variables set in the controller into a view file. For example:

<p>Welcome back, <?= $name ?>!</p>

Unfortunately this approach falls down when you find yourself deploying to a server that has had PHP compiled with short tag support off. The above code will not be parsed by the PHP engine… but the presence of angle-brackets will mean that you won’t see the unparsed output on the web page; so you end up with blank spaces, viz:

Welcome back, !

The ‘fix’ for this laziness is, of course, not to use short tags, even when outputting the simplest of variables:

<p>Welcome back, <?php echo $name; ?>!</p>

It is also a good practice to get into in readiness for PHP6, which will be removing the ability to use short tags altogether.

Don’t rely on truthy and falsey values

Like several other languages, PHP has a concept of truthiness and falsiness when it comes to evaluating boolean expressions. The number zero, an empty string, NULL or undefined will all evaluate to FALSE in a simple expression:

$x = 0;
$y = '';
if ($x || $y || $z) {
  echo "This will not be displayed";

(Yes, I know you can test if a variable is actually FALSE by using the triple-equals sign === in the conditional, but that’s not what this point is about.)

So we know that we can rely on PHP returning FALSE whenever we test a non-existing, empty or zero variable. Using this knowledge, we can check for the presence of incoming settings before doing things:

<?php if ($_GET['foo']): ?>
  <p>You submitted the foo item.</p>
<?php endif; ?>

We can even write quite neat little loops using array indices:

while ($myarr[0])

So where’s the problem here? Well, all of those tests for non-existent variables or array items will throw a PHP E_NOTICE level error. Usually this isn’t a problem; most apps and PHP installations set the default error reporting value to E_ALL & ~E_NOTICE, which is to say they do not include E_NOTICE errors. No errors are shown on your web pages, and everything is fine.

That is, until you notice that the error_log on your live server has filled up with over a gigabyte of PHP errors per day. Yup, it’s another server configuration issue, this time one that writes every single notice to a text file. And if, like me, you were relying on the above behaviour then that text file gets very big, very fast.

To fix this problem just takes a little more discipline when coding. In short, always check for the presence of a variable or array key before checking its value:

<?php if (isset($_GET['foo']) && $_GET['foo'] == 'bar'): ?>
  <p>You submitted the foo item.</p>
<?php endif; ?>

Now the first part of the conditional—isset($_GET[‘foo’])—will fail, and the second part with the non-existent array key will never be evaluated.

Feb 10

One quick thought of my own on the new Apple iPad

10:20pm on Wednesday 10th February, 2010

So I just spent my lunch hour catching up with my neglected feedreader (tip: never let your feeds pile up over an Apple event!) and I haven’t seen anyone else raise this point, so here goes.

I don’t know about you, but personally my 16Gb iPhone is mostly full of music. There are a few odd podcasts, less than a hundred photos, and a couple-dozen apps, but for the most part—70, 80-percent—it’s music that takes up the space.

And that makes sense for what I use it for—as a phone, a portable music player, a games device and, occasionally, a camera.

Now consider the new Apple iPad, which comes in 16Gb, 32Gb and 64Gb sizes. If its primary target market is folks sat on their sofa, idly surfing the web, dealing with emails or playing games, does music really fit into that usage profile? I can’t imagine that the built-in speakers are that much cop, plus if you’re moving the thing around you’re hardly experiencing the optimal listening experience. Earphones? Not convenient, not like being able to slip your iPod or iPhone into your pocket when you need to get up and go somewhere. And anyway, who doesn’t have some other means of listening to music?

So what is going to take up all that flash drive space? It has various “Productivity” apps—word processing, spreadsheets, and so forth—but those don’t take up much space. iBooks? Again, they’re mostly text, they don’t need the space either.

So it’s got to be apps…

...and lots of them. Is Apple betting on the iPad to drive even more growth in App Store sales than they’ve already seen with the iPhone and iPod Touch?

And if you have trouble keeping track of a few dozen apps on your iPhone, how will you cope with a few hundred on an iPad?

Feb 09

Potential EE add-ons: What would you like first?

10:56pm on Tuesday 9th February, 2010

Partly because I really don’t know, but mostly because I haven’t got anything else to write about this week for Project 52, here is a list of potential ExpressionEngine add-ons I plan to build—and I’d like you to tell me which to do first.

Of course, it’s entirely possible that someone has already done any or all of these and I just haven’t found them yet… in which case please point me in the right direction and save me a ton of unnecessary work!

Related fieldtype dropdowns

If you ever have a client with thousands of pages (or products or whatever) that wants to use related entries, the default dropdown format isn’t very useful for them. This add-on will replace some or all related fieldtypes with those snazzy “search as you type” Ajax-powered search fields. Neato!


Can’t make an ExpressionEngine add-on without a double-e pun, right? This idea is an extension to the current way categories work when you delete one that has entries; instead of just leaving a bunch of orphaned entries, it will prompt you to re-categorise them.

Category Image URL Fieldtype

Hopefully a simple one, this—lets you use a helpful file manager fieldtype for the Category Image URL field. At the moment it’s just a text field, which is not exactly helpful for non-technical clients. Replacing it with something like the nGen File Field file upload tool would be very handy if you rely on category imagery.

Mac OS X Dashboard Widget

Okay, this last one isn’t exactly an EE add-on, but I find it very handy. It’s a dashboard widget for Mac that just lists all the latest comments on any of your pages, and lets you click through to edit or delete them. It’s very useful if like me you don’t get to see any ‘new comment’ emails until you get home but want to stay on top of comment spam. I guess it could also be used to keep a count of things like caught spam or Akismet’s tally too.

Cast your vote now

Alright, I’m not actually taking votes, but I’d be interested to see what people think of these potential add-ons, and if there’s a clear winner I’ll make that my priority for development. Tell me what to do, please…

Jan 31

Reading List 2009

3:26am on Sunday 31st January, 2010

Just as I have done for the last two years, I’ve been carefully recording my reading material. 2009’s repository was Nathan Borror’s excellent new web app, Readernaut - and the final total is a not completely unimpressive thirty.


Still trying to improve my consumption of “classic” literature, I slogged through Midnight’s Children last year, which was not an easy read but ultimately rewarding. The only other book that really made an impression was the excellent high-concept novel, The Time Traveller’s Wife.

  • My Favourite Wife (Tony Parsons)
  • The Time Traveller’s Wife (Audrey Niffenegger)
  • Good Omens (Terry Pratchett, Neil Gaiman)
  • Revolutionary Road (Richard Yates)
  • By Design (Richard E Grant)
  • A Matter For Men (David Gerrold)
  • Farnham’s Freehold (Robert A Heinlein)
  • Time For The Stars (Robert A Heinlein)
  • Ysabel (Guy Gavriel Kay)
  • Midnight’s Children (Salman Rushdie)
  • The Magicians (Lev Grossman)
  • Requiem for a Dream (Hubert Selby Jr)
  • Nation (Terry Pratchett)


As I’ve been travelling a lot this year, I occasionally found that I didn’t have the bag space to fit a book into my overnight bag. Thus, eBooks on iPhone have made their first appearance on my reading list.

  • The Adventures of Sherlock Holmes (Arthur Conan Doyle)
  • The Curious Case of Benjamin Button (F Scott Fitzgerald)
  • A Princess of Mars (Edgar Rice Burroughs)


  • The Audacity of Hope (Barack Obama)
  • Outliers (Malcolm Gladwell)
  • Droidmaker (Michael Rubin)

Droidmaker, the story behind the birth of movie special effects and George Lucas’ role in that art’s genesis, was actually a free PDF recommended by Michael Heilemann of Binary Bonsai, but I’d certainly pick it up for a coffee table book if I saw it in the shops. It was an excellent geek read.


Yet more fantasy to pad out my reading list. This year I discovered Robin Hobb, and I’m slowly slogging through her various trilogies. Looking forward to Joe Abercrombie‘s new book, due out sometime in 2010.

  • Best Served Cold (Joe Abercrombie)
  • Tigana (Guy Gavriel Kay)
  • Assassin’s Apprentice (Robin Hobb)
  • Royal Assassin (Robin Hobb)
  • Assassin’s Quest (Robin Hobb)
  • Ship of Magic (Robin Hobb)
  • The Mad Ship (Robin Hobb)

Graphic Novels

I re-read Watchmen before going to see the (excellent, faithfully adapted) film in March.

  • Watchmen (Alan Moore, Dave Gibbons)
  • World War Hulk (Greg Pak)
  • Batman: The Killing Joke (Alan Moore, Brian Bolland, John Higgins)
  • Batman: Arkham Asylum (Grant Morrison)

Highlights of 2009

Despite reading more than in 2008, it’s difficult to pick out any real standout books from the preceding lists. The Time Traveller’s Wife was clever but ultimately forgettable; Midnight’s Children was impressive but hard work. So no real recommendations from me, just a reaffirming of my intentions to actually read some more “proper” literature in the coming twelvemonth.

Jan 25

My World of Warcraft

4:58am on Monday 25th January, 2010

I don’t often mention things I do in my spare time on this blog, but this week I’m going to make an exception and talk about the only game that I could really claim to play: World of Warcraft.

Now I’m not much of a gamer

I have Call of Duty 4 but never play it, and a couple of Lego games on the Wii, but I’ve never really dedicated all that much of my life to completing video games. There’s no reason I couldn’t get myself a Playstation or Xbox, but I tend to think that taking over the living room television to kill terrorists or trash Liberty City is kind of unfair to my wife, who prefers to use the telly in the evening for what is, to be fair, its intended purpose.

So, no real console, and as a Mac user I’m not exactly blessed with a wide selection of computer games to choose from.

Luckily one of the few games to get a Mac conversion is Blizzard’s runaway success, World of Warcraft.

For The Horde!

I originally started playing in late 2008 after avoiding it for years, and was immediately sucked in by the immersive world, rewarding progression and social interaction. Sucked in a little too far, as it turns out; when I found that I was spending more time reading strategy guides and wowwiki entries on DPS gearing than I was enjoying the game, I uninstalled it and cancelled my account. I didn’t want to be one of those guys with spreadsheets full of cross-referenced armour points, committed to four hours a night raiding. I left my Level 53 Priest on his horse in Un’Goro Crater and quit.

Last year I went back, but this time it’s different. I don’t care about gear and quick levelling - no addons for me this time around - the only reason to play is for the fun of it. And whatever its detractors might say about geeks pretending to be elves, it is a lot of fun; it’s got that perfect balance of carrot and stick to constantly have you questing after the ever-so-slightly-better weapon or piece of armour, and the satisfaction of bringing down a particularly troublesome bad guy with the help of a random bunch of people willing to stop what they are doing and help out a stranger is better than any Xbox achievement.

Of course, the real reason for this post is that I wanted an excuse to use the new, embeddable Armoury viewer and show off my current main character:


I’ve kind of reached something of a platform now that he’s Level 80. Once you hit that top level it gets harder and harder to avoid needing to know your stats if you want to progress, but I really don’t want to be constantly comparing armour bonuses and running the same dungeons over and over for that elusive cloak. I did my first raid today (until latency overcame me and I had to drop out), but that becomes even more a time-suck.

Still, Cataclysm comes out this year, bringing with it two completely new races to play. Oh, and destroying the World As We Know It as well, which should go some way to eliminating the boredom that is just starting to creep in.

Jan 14

How to make a quickstart folder for your projects

8:15pm on Thursday 14th January, 2010

Here’s a simple little tip to save a few precious seconds each time you sit down to start work on a website project.

Bookmark This

This is certainly true for me, and probably true for all web developers—when you are working on a project, there is a set of sites and URLs that you need to have open. For me this usually means:

  • The project to-do list in Basecamp
  • The site on my localhost
  • The site’s control panel
  • phpMyAdmin
  • The ExpressionEngine documentation
  • php.net (for looking up the occasional function or when I can’t remember those damn date formatting letters)

An open bookmarks folder on Firefox's toolbar

Now you could just open up each site as-and-when you need it, but one trick that I’ve discovered is to place all of those links into a folder on your browser’s Bookmarks Toolbar (I keep mine under a master folder named “Clients”). Now when you sit down to work on something, go to that folder and Ctrl-click on it (Cmd-click on Mac) or select the “Open All in Tabs” option. This shortcut will open up every link in the folder as a new tab; with just one click, your browser is now set up with everything you need to get started on that project.

Development vs. Live

This technique can be extended to cover Development vs. Live environments too. Perhaps when working with the live site you need to add your Plesk control panel or links to other third-party services that you are using—just include any frequently accessed sites in the relevant folder, and you’re one click away from being ready to work.

So there you have it

A simple way to save yourself a little wasted time while you work on the Next Big Thing™.

Jan 06

New Year’s Resolutions // Project 52

BloggingExpressionEngineFreelancingPersonalThe Site
12:39am on Wednesday 6th January, 2010

Perhaps I should feel bad that last year’s “Resolutions” post is still languishing in my Drafts folder, not so much unfinished as barely started. But 2009 kept me so busy that I barely had time to think, let alone blog. That is something I intend to change in 2010.


Last year was the first working directly for the Amsterdam office at Booking.com, and the regular travel that entails means that my carbon footprint has taken on Sasquatch-like proportions. I also managed to squeeze in a third trip to South By South West in March, and a holiday in the Lake District before it all went under water.

2009 was also my busiest freelance year ever, although (happily) that actually meant fewer actual clients. Working with other local freelancers like Digital Spoke and Creative Freedom meant I could concentrate on what I do best - which, this year, has been exclusively ExpressionEngine development. I even managed to make it to the first ever EECI conference in Leiden in October, where I met old friends and took far too many notes.

2010 Resolutions

  • Less freelance work. While I’ve definitely learned a lot about what ExpressionEngine can do this year, and the extra money has been nice, I’m going to try to cut down on freelance work this year to spend more time with my family and on projects around the house.
  • Get fit. A side-effect of spending all my time in front of a computer has been a general deterioration in my health - this year will be spent getting back in something resembling shape. Of course, being a geek this may involve gadgets and web apps; more on this topic when I start my Geek’s Guide To Getting Fit later this month.
  • Update this site. Not a redesign, but this site badly needs some attention. It’s still running EE 1.6.5 for God’s sake! When I launched it last January I had a to-do list of remaining tasks that has only grown as I’ve neglected it in favour of paying work.
  • Less travel. No SXSW for me this year, and probably no conferences other than work ones.

And finally on the list of New Year’s resolutions…

Project 52

My friend and talented artist Anton Peck launched Project 52 late last year. From the site:

Project 52 is a personal challenge geared toward getting fresh content on your website. The goal is to write at least one new article per week for one year.

If you ignore the flurry of activity in October following my trip to the EECI conference, I only managed a paltry seventeen posts last year, so this year I’ll be joining over 600 other people and writing a lot more on this blog as my contribution to Project 52. I already have several juicy ideas lined up for you lucky people, including a complete rewrite of my simple PHP shopping cart script so I have somewhere to direct the people who still send me weekly support request emails over five years after I wrote the damn thing. (And massive congratulations to Anton for kick-starting this project. Over 600 people - that’s more than thirty-thousand new pieces of content!)

So that’s the plan

Less work, more exercise, less travel, more writing.

I’m quite looking forward to 2010.

Oct 26

Jonathan Longnecker - From Design To Dynamic: Rapid Development with ExpressionEngine

7:30pm on Monday 26th October, 2009

Jonathan Longnecker is a developer with fortyseven media. He discussed the tips and tricks they use to quickly build new ExpressionEngine sites.

Slides and code examples from the talk are on Jonathan’s site.


  • The problem is that EE developers are too awesome. Add-on development has exploded, and functionality and usefulness is really amazing. Structure is a great example of this.
  • We typically use 15+ addons for every site, with the same kind of templates and global variables
  • The solution is to set up a sandbox site where the core and all add-ons are kept up-to-date. Add some default templates and global variables, a weblog for content, and some sweet tricks and you have the ability to rapidly build out new sites
  • We will be adding new things to it as we find great add-ons


  • LG Addon Updater
  • LG htaccess Generator: Generates your .htaccess file, removes index.php and much, much more
  • LG Add Sitename: Enables Control Panel admin page title replacements, client logo
  • LG TinyMCE: Not convinced it’s the best choice, and it’s not good with pasted text. Turn off source formatting, spans and brs, take out the image upload, add blockquote
  • SL Developer Info: Lists all weblogs, templates, and other useful developer shortcuts. Give it it’s own custom tab in your nav bar
  • ImgSizer: Resizes and crops intelligently and creates thumbnails; make sure you create a “sized” directory in your images folder
  • Solspace’s Freeform
  • FieldFrame: Changes the way you can put together certain types of content
  • nGen File Field
  • Structure: Radically changes the way you handle content pages and navigation. Scared of using it initially as I thought it would lock me into certain way of developing templates, but it really has potential to speed up certain parts of your site; secondary static pages are a lot faster to set up

Tips and tricks

  • In your Template Preferences, turn on save template revisions (I use five) for added protection from mistakes, and always save templates as files
  • Create a “content” weblog with custom fields - meta keywords, meta description, a body (TinyMCE field type), and images (an FF Matrix). A sweet trick invented by AJ Penninga is to set up your images as a FF Matrix with a File field, title, radio group of sizes, radio group for crop height (optional), and dropdown for alignment. Then to insert the image add {image_1}, {image_2}, etc. in the body content. Your content template then uses LG_Replace to loop through the matrix images and replace those tags with the images inside the {images} tag
  • Create a client member group with access to file uploads, Structure and weblogs
  • Create global variables: I use html_head (containing doctype, static meta tags, favicon link, etc.), html_closing, jquery, javascript, rss (just your RSS links), and stylesheets
  • Create templates in site and _global groups: footer, header, nav (containing Structure’s nav_main tag), sidebar (using Structure’s nav_sub tag) and content (using Structure’s title_trail tag to build the </code> element)</li> <li>Keep the <code><body></code> tag inside each template so you can add a dynamic CSS id or class to it</li> <li>Replace the default homepage with a list of what’s been installed and configured on the sandbox site</li> <li>Moving servers is now faster than installing a new site, as the sandbox site is ready to go - just copy the database and files over and amend the <strong>config.php</strong> settings</li> </ul> <p>Jonathan ended with a live demonstration of creating a new site from scratch, using Structure to create pages and place them in the site <abbr title="Information Architecture">IA</abbr> really quickly, generate automatic navigation, and use Structure’s Listings feature to attach weblog entries to a page (a la a design portfolio). Structure makes it impressively easy to re-order navigation items. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/pittock.jpg" id="article_image" alt=""> <div id="content"> <h1>Jamie Pittock - The Art Of Proactive Parenting</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C15/business">Business</a>, <a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a>, <a href="http://v4.thewatchmakerproject.com/category/C16/freelancing">Freelancing</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>7:27pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Jamie Pittock is Operations Director for Nottingham-based <a href="http://erskinedesign.com/">Erskine Design</a>. He discussed effective ways to develop ExpressionEngine sites that increase understanding and remove uncertainty for your clients.</p> <p>Jamie’s slides can be viewed on <a href="http://www.slideshare.net/jamiepittock/the-art-of-proactive-parenting">SlideShare</a>.</p> <h2>Managing client expectations</h2> <ul> <li>Design your content model around the client’s existing content - take example content from client, and identify the fields, types and field names needed</li> <li><abbr title="What You See Is What You Get">WYSIWYG</abbr> - clients come wanting total control of their content. They are proposing a solution before you understand their problem. Often they just have specific issues. Designers get lazy and clients shouldn’t design</li> <li>You need to think about how you would write this content. Create a template to give to their content creators. <a href="http://www.ngenworks.com/software/ee/ngen-file-field/">nGen File field</a> is the best solution for files at the moment</li> <li>Live Demo: The new ed_imageresizer plugin from Erskine does image resizing on the fly and caches results. It will be available soon</li> <li>Don’t always have to give the client what they ask for. e.g. No WYSIWYG, just multiple images/captions/alignment fields for main body and extended text. We use Textile. What if they want more images? You can only design and model content based on what the client tells you at the time. Don’t be afraid to tell the client that</li> <li>Audience comment: “Publishing online is <strong>not</strong> creating Word documents.”</li> <li>Influence and advise client using size of fields, instructions, options available</li> <li>Make it fun. Clients need to enjoy managing their site. Make them feel like designers. Enable them to do something they never thought they’d be able to do. Make it feel less like work (and less like Word)</li> </ul> <h2>Improve the Control Panel</h2> <ul> <li><strong>#8 Signpost using tabs.</strong> Make tabs for things the client needs access to</li> <li><strong>#7 Remove what isn’t needed.</strong> Current dashboard is laughable; get rid of notepad, bulletins, comments, etc. Same on Edit tab - opportunities to remove confusion - remove trackback column, comment count, etc.</li> <li><strong>#6 Improve usability.</strong> Add hover dropdown on edit tab, install <a href="http://expressionengine.com/downloads/details/edit_tab_ajax/">Edit Tab AJAX extension</a></li> <li><strong>#5 Add extra content.</strong> Add extra columns to Edit page (e.g. Categories)</li> <li><strong>#4 Content Previews.</strong> Use Live Look. Fix the Publish page buttons and kill the default ‘Saved’ page using the <a href="http://www.ngenworks.com/software/ee/publish-tweeks/">Publish Tweaks extension</a></li> <li><strong>#3 Use jQuery to change stuff.</strong> For example, change the label for the title field on Publish page depending on the weblog they are using. Avoid client confusion. Remove Options checkboxes dynamically. Tiny changes can make a difference to client understanding</li> <li><strong>#2 Use field instructions.</strong> Include image dimensions, or more complex details. Use jQuery or extensions to add additional detail. Say how content will be displayed</li> <li><strong>#1 Create a new theme.</strong> This is a lot of work. Does this breach the license agreement? Don’t know, maybe</li> </ul> <h2>Q&A</h2> <p><strong>How much training do you provide?</strong><br /> No documentation - we create videos and offer staff training. It’s important to bring the client in as early as possible and get them using EE.</p> <p>It was also interesting to note that Erskine keep their templates under an /assets/templates/ folder (outside of the system folder). </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/burdick.jpg" id="article_image" alt=""> <div id="content"> <h1>Paul Burdick - Add-On Development: EE Expects That Every Developer Will Do His Duty</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a>, <a href="http://v4.thewatchmakerproject.com/category/C17/php">PHP</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>7:24pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Paul Burdick is the ex-CTO of EllisLab, and now works as Lead Developer for ExpressionEngine add-on shop <a href="http://www.solspace.com/">Solspace</a>.</p> <p>Download Paul’s slides here in PDF form: <a href="http://bit.ly/addons_eeci2009">http://bit.ly/addons_eeci2009</a>.</p> <h2>All about add-ons</h2> <ul> <li>What are add-ons? There are three types - extensions, modules and plugins</li> <li>Extensions extend basic EE functionality, allow you to interpose your own code. Developers are extending the idea by adding their own hooks in their modules. Typically extensions don’t have a database table, but do have settings in the Control Panel</li> <li>Modules are the “mighty workhorses” of EE. They typically have a Control Panel area, database tables, and their own template tags</li> <li>Plugins have no settings and no install process. They offer text manipulation via template tags or custom fields</li> <li>On <a href="http://devot-ee.com/">Devot:ee</a> the add-ons currently break down as 51% plugins, 35% extensions, 15% modules</li> <li>EE 2.0 will introduce Accessories - tools, references and abilities that go at the bottom of the CP. They can have database tables, and use View files. Defaults include Learning, Notes, Tips</li> </ul> <h3>Developing add-ons</h3> <ul> <li>Necessary skills you will need to be an add-on developer: PHP (learn at <a href="http://php.net/">php.net</a>, <a href="http://www.w3schools.com/PHP/">w3schools</a>, and <a href="http://www.zend.com/">Zend</a>), SQL (note that Active Record is part of EE 2.0)</li> <li>View files are HTML with PHP in, and are used in EE 2.0 (they can also be used in 1.6.x with <a href="http://www.solspace.com/software/detail/hermes/">Solspace’s Hermes</a>). They are much easier to write than using the Display class</li> <li>Build your UI in static HTML/CSS/JavaScript first before converting to View files. It’s easier to test that way, and specialist UI developers don’t need to know PHP</li> <li><a href="http://jquery.com/">jQuery</a> is available by default in EE 2.0 (although it’s not the best way to learn JavaScript). EE 2.0 also makes it easy to use other JS libraries</li> <li>Never, ever just start coding! Don’t just write code and release it. Do research - look at previous releases, how are big companies doing it, What are your required features</li> <li>There are a lot of add-ons that do not need to exist. The <a href="http://expressionengine.com/docs/modules/query/index.html">Query module</a>, or JavaScript+AJAX can do a lot</li> <li>Is a module required? Could an extension do it? Or a plugin that outputs weblog data?</li> <li>Tell a story - how would a user do this? What would Apple do? Eliminate steps, follow your instincts</li> <li>Map out features - major, minor, and “icing”</li> <li>Include your own hooks for future expansion</li> <li>Database structure - plan your tables, with separate ones for preferences and data. How does your add-on interact with EE’s own tables? <a href="http://en.wikipedia.org/wiki/Database_normalization">Normalization</a> - eliminate data duplication</li> <li>Use specific, sensical field names</li> <li>Use indexes</li> <li>When naming template tags, give them a good name, and describe the parameters and variables in the comments. Explain what each one does</li> <li>Make tag name simple and obvious. I want to be able to read the template and know what it does. No abbreviations</li> <li>Parameters - use prefixes to namespace parameters and group functionality</li> <li>Variables - there should be no ambiguity and no abbreviations. Name variables the same as their corresponding database field, then you can just loop through a query result row to find and replace. Prevent collisions in variables. <li>Underscores are recommended</li> <li>Get feedback - revise your add-on spec until solid</li> </ul> <h3>Building an add-on</h3> <ul> <li>Break the Control Panel page into sections: Data (create, modify, delete); Preferences/Settings/Permissions (copy preferences is a handy tool to provide); Actions - recount records, cache management; display the version number and documentation link</li> <li>Keep it simple - build what is necessary and no more</li> <li>Build it in HTML/CSS/JavaScript first; use a view file, put the PHP into the HTML (not the other way around), and ignore IE6 (EE 2.0 and Solspace do)</li> <li>Have goals and milestones not deadlines. Don’t release software until you think it’s ready</li> <li>Writing code - follow the <a href="http://expressionengine.com/docs/development/guidelines/index.html">EllisLab developer guidelines</a>! Comment well and properly. EE code has jokes and ASCII art in it</li> <li>Sanitize and escape everything. Assume all data is tainted - sanitize and escape at the query, not at the top of your class</li> <li>Abstraction - use twice, write once. Create libraries - reduces work and mistakes</li> <li>Simplify - bail out of the process first, as soon as you find a problem, do the actual work second</li> <li>Reduce database work. Multiple queries are okay; validate, check pagination with a COUNT query, and only then retrieve data</li> <li>Consider using a Model to abstract queries</li> <li>Per page load caching - use <code>$SESS->cache[‘modules’][‘module_name’][some_cache’] = array();</code> to cache query results, preferences, etc. Use a reference</li> <li>If you need weblog data, just <a href="http://gist.github.com/197721#expressionengine">use the Weblog module</a> - <code>include()</code> it and call its methods</li> <li>Provide tools for keeping things tidy - remove old data/caches, optimize tables (regularly or provide a button to do so)</li> </ul> <h3>Debugging and improving performance</h3> <ul> <li>Debugging and performance are the same thing</li> <li>Turn on error reporting - no PHP errors ever!</li> <li>Turn on SQL queries - review your queries, check CP, settings, tags in templates - eliminate duplicate queries!</li> <li>Are certain queries necessary on every page load? Validate and check cache. Evaluate queries for performance - to improve things, try adding a WHERE clause on an indexed field, and remove extraneous JOINs</li> <li><a href="http://en.wikipedia.org/wiki/Denormalization">De-normalization</a> - duplicate data to reduce work. Abstract methods for data consistency</li> <li>Learn about MySQL performance - <a href="http://www.mysqlperformanceblog.com/">mysqlperformanceblog.com</a> is a good resource</li> <li>Turn on <a href="http://expressionengine.com/docs/cp/admin/system_preferences/output_and_debugging_preferences.html">Template Debugging</a> - what code is taking the longest to run? You can add debug entries in your code, e.g. before and after a query or loop, using <code>$TMPL->log_item();</code></li> <li>Embeds are heavy - they run all the “new page” queries for each one. Automated actions - slow down your add-on. Use AJAX instead</li> <li>Use <code>trigger_error()</code> to throw errors for deprecated code</li> <li>Ask for help. Often just discussing a problem will lead to a solution</li> </ul> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/ryan.jpg" id="article_image" alt=""> <div id="content"> <h1>Ryan Irelan - Ten Ways To Supercharge Your EE Development</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>6:31pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Ryan Irelan works for <a href="http://www.happycog.com/news/2009/08/merger/">Happy Cog West</a>, and is also responsible for <a href="http://eescreencasts.com/">EE Screencasts</a>, the <a href="http://eeinsider.com/">EEInsider</a> site, <a href="http://eescreencasts.com/page/ee-help-chat">EE Help Chat</a>, and the <a href="http://ee-podcast.com/">EE Podcast</a>. He is working on an ExpressionEngine book that will cover EE 2.0.</p> <p>Follow along with Ryan’s slides over on <a href="http://www.slideshare.net/ryanirelan/ten-ways-to-improve-your-ee-development">SlideShare</a>.</p> <h2>Top Ten Tips</h2> <ul> <li><strong>#10 Pre-package your EE install.</strong> Install and configure your favourite add-ons, setup system preferences, create default weblogs, configure your favourite tab arrangement, enable extensions and modules, and setup default members and groups. Export it all into a SQL file and zip up the files = default EE installation. I’ve converted all this into a shell script</li> <li><strong>#9 Use Version Control.</strong> It adds an extra layer of security, as well as version tracking. Happy Cog West uses a remote database due to the difficulty of merging database schema changes; all staff/management/designers use <a href="http://subversion.tigris.org/">Subversion</a></li> <li><strong>#8 Config Variables.</strong> You can use <strong>config.php</strong> to store other configuration variables (e.g. you can put FieldFrame paths in it). EE will honour config variables over the database value. There is a <a href="http://expressionengine.com/wiki/Hidden_Configuration_Variables/">list of config variables</a> on the ExpressionEngine Wiki</li> <li><strong>#7 Avoid Add-On Insanity.</strong> There are sites that use too many add-ons, making itdifficult to figure out what has happened when something goes wrong. Find more creative solutions to problems (e.g. you don’t need an add-on just for a “Tweet this” link)</li> <li><strong>#6 Optimize Now (And Later).</strong> Make use of the <a href="http://expressionengine.com/docs/modules/weblog/parameters.html#par_disable">disable parameter</a> as you code (i.e. don’t plan to go back and add it later). EE also has ‘extreme traffic overrides’ - you can disable all tracking as a quick fix to site traffic problems. Solspace offer a <a href="http://www.solspace.com/development/performance/">site evaluation service</a></li> <li><strong>#5 Become Fan<em>tab</em>ulous.</strong> Add as many tabs as you need to get to the stuff you use regularly. You can even <a href="http://eeinsider.com/tips/view/save-common-entry-filters-as-tabs/">save edit filters as tabs</a></li> <li><strong>#4 Developer Add-Ons FTW.</strong> <a href="http://www.experienceinternet.co.uk/resources/details/sl-developer-info/">SL Developer Info</a> and <a href="http://devot-ee.com/add-ons/extensions/pur-developer/">Pur Developer</a> add pages or links to your Control Panel full of developer-specific information. <a href="http://leevigraham.com/cms-customisation/expressionengine/lg-add-sitename/">LG Add Sitename</a> allows you to display server time settings in the header</li> <li><strong>#3 Keep An Eye On The User.</strong> Make it easy for the user, not for you. Set up default tabs for users, use custom field groups for content instead of one catch-all group, keep the control panel as clean as possible, remove the formatting bar and dropdown, turn off the url title field, turn off dates if they’re not important. Don’t have to tell clients “Don’t worry about it” if they never see it!</li> <li><strong>#2 Try <a href="http://buildwithstructure.com/">Structure</a>.</strong> It’s a free module; I didn’t try it for a long time, but now I have I’m really impressed</li> <li><strong>#1 Take A Chance.</strong> Step outside your comfort zone with your tools; try writing an extension</li> </ul> <h2>Q&A</h2> <p><strong>What do you recommend for deployment?</strong><br /> Tried <a href="http://www.capify.org/index.php/Capistrano">Capistrano</a>, Git+Capistrano, but not found a magic bullet for that - would love to hear if anyone has one.</p> <p><strong>Why do you work with a remote database?</strong><br /> Only with team, not on solo projects; it’s slow using remote db, but stops conflicts.</p> <p><strong>Have you had issues with performance on related entries?</strong><br /> Yes, we have had to write custom queries sometimes.</p> <p><strong>Is the use of config.php variables automatic or does the developer have to code for that?</strong><br /> EE does the check, but you do have to code for it yourself in your add-on. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/leevi.jpg" id="article_image" alt=""> <div id="content"> <h1>Leevi Graham - How to start developing your own add-ons</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>6:27pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Leevi Graham runs <a href="http://newism.com.au/">Newism</a> in Australia, and has developed more than 25 add-ons over the last two years. His first and most profitable add-on was <a href="http://leevigraham.com/cms-customisation/expressionengine/lg-better-meta/">LG Better Meta</a>, and Leevi was named <a href="http://devot-ee.com/articles/item/first-annual-academee-awards/">2008 Add-on Developer of the Year on Devot:ee</a>.</p> <p>Download Leevi’s slides (PDF) here: <a href="http://bit.ly/efYkA">http://bit.ly/efYkA</a>, or watch the <a href="http://vimeo.com/7571463">video of his presentation</a> on Vimeo.</p> <h2>About Add-Ons</h2> <ul> <li><a href="http://expressionengine.com/docs/development/plugins.html">Plugins</a> render front-end tags. They are simple to build, offer custom field text formatting, use a single file, have no Control Panel administration, no settings, and can’t process forms. 99% of plugins are for the front-end</li> <li><a href="http://expressionengine.com/docs/development/tutorial.html">Modules</a> are 50/50 front-end and back-end. It is easy to upgrade a plugin to a module; they can process form submissions, use multiple files, but have no settings</li> <li><a href="http://expressionengine.com/docs/development/extensions.html">Extensions</a> let you “take control” of EE. They extend existing tags or the control panel, have a built-in settings form, and are all done through EE’s built-in hooks. Extensions must be activated to use, and don’t offer tag parsing. Hook registration can be complex for beginners</li> <li><a href="http://expressionengine.com/developers/extension_hooks/">Hooks</a> hook into the core EE processing, and there are over 170 of them. An extension’s class method is called when it’s hook is executed; you can see <a href="http://devot-ee.com/hooks/">which hooks are used where on Devot:ee</a></li> <li>Your code should always check whether someone else has already used the same hook</li> <li>If you are developing a combined extension and module, I recommend you put settings specific to the extension into the extension, rather than in the parent module</li> <li>Add-Ons combine extensions, modules and plugins. This means lots of files in different locations, with dependencies on one another</li> <li>Where to find add-ons: <a href="http://expressionengine.com/downloads/addons/">Official repository</a> (144), the <a href="http://expressionengine.com/forums/">EE forums</a> (?), <a href="http://devot-ee.com/">Devot:ee</a> (480), <a href="http://github.com/search?q=ee_addon">GitHub</a> (114)</li> <li>For help developing add-ons, there is <a href="http://expressionengine.com/developers/">documentation</a> and a <a href="http://expressionengine.com/developers/extension_hooks/">list of hooks</a> on the EE site</li> <li>If you put your code on GitHub, community has adopted the <strong>xxx.my_addon_name.ee_addon</strong> naming convention</li> </ul> <h2>Leevi’s Development Process</h2> <ul> <li>I’ve started providing templates and themes incorporating the add-on so that users can see that the add-on works, rather than struggling to work through the code themselves</li> <li>Always end extension classes with <code>_ext</code> to prevent class naming conflicts</li> <li>Documentation is important; it’s the most boring job, but if you do it properly and provide examples, your support requests will more than halve</li> <li>If an add-on is worth writing, it probably should be for sale - so charge for your extensions</li> <li>But without releasing free stuff initially, I wouldn’t be in the position I’m in now, so it’s a balancing act</li> <li>Currently offers email-based support (<a href="http://brandon-kelly.com/">Brandon Kelly</a> uses <a href="http://getsatisfaction.com/">GetSatisfaction</a>)</li> <li>Free LG or NSM add-on licenses for everyone at EECI2009!</li> </ul> <h2>Q&A</h2> <p><strong>Is it worth spending the time to build a payment system handler so you can sell?</strong><br /> Yes - you might spend a week building something, but you can then use that to sell for years.</p> <p>Leslie Camacho (EllisLab President) noted that lots of hooks were stripped out of EE2.0 for the beta phase to limit developers and reduce bug report complexity. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/boyink.jpg" id="article_image" alt=""> <div id="content"> <h1>Michael Boyink - Quoting and Planning ExpressionEngine Projects</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C15/business">Business</a>, <a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a>, <a href="http://v4.thewatchmakerproject.com/category/C16/freelancing">Freelancing</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>6:24pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Michael Boyink is a <a href="http://www.boyink.com/">consultant</a> and <a href="http://train-ee.com/">trainer</a> who has been working with ExpressionEngine since 2002. He discussed his process for planning and quoting on EE projects.</p> <p>Watch <a href="http://vimeo.com/7570396">Mike’s presentation over on Vimeo</a>.</p> <h2>Pitching and quoting EE</h2> <ul> <li>I pitch EE as a commercial product that has people working on it for a living, paid tech support staff, security, and great community</li> <li>You don’t need to know the size of a site to quote for it any more. Now we need to know how many weblogs/channels it will have. All other aspects - fields, groups, templates - all depend on the number of channels</li> <li>There are always other pieces is of content that don’t fit</li> <li>Look through the site and identify unique content types</li> <li>Other things that add complexity: complex content types, IA complexity, frontend complexity, people, the server environment</li> <li>Also: don’t forget project management, other things that need to be done in the project (e.g. content importing)</li> <li>Come up with a range of project hours, then give it a gut check - does it feel right? Come up with a final cost. Billing by hours is bad - the better you are, the less you can charge</li> <li>I usually give a ballpark figure so the client can decide whether they want the full quote/proposal</li> </ul> <h3>Office walls</h3> <ul> <li>Everything goes up on a project wall - the quote, a site map, content and designs. With everything in front of you it is easy to spot issues (e.g. the <li>design doesn’t accommodate the content, or IA issues)</li> <li>Post new versions over the top of old ones; kind of paper-based version control. Never take anything off the wall</li> <li>Build deep content first so the client can start entering their data earlier</li> <li>The project board is a good way to jump back into a project after time away</li> </ul> <h2>Q&A</h2> <p><strong>Do you charge ongoing costs?</strong><br /> Don’t do it, in fact I sell against it in proposals, and don’t charge for doing upgrades.</p> <p><strong>How do you do training?</strong><br /> Offer a visit, screencast, or documentation. Clients usually prefer on-site visit.</p> <p><strong>How do you charge for licenses?</strong><br /> The client buys the license, so they own it.</p> <p><strong>Who should populate the content?</strong><br /> We can do it, but it’s better - and good training - for the client to do it.</p> <p><strong>Do you ever customise the Control Panel?</strong><br /> No, never needed to; sites either don’t need it done, or there isn’t the budget for it.</p> <p><strong>What add-ons do you use or recommend?</strong><br /> Don’t really use them - I’m very careful to keep EE as clean as possible to be ready for 2.0. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/brandon.jpg" id="article_image" alt=""> <div id="content"> <h1>Brandon Kelly - Make A Market Out Of Our Community: The Whys and Hows of Selling Add-Ons</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>6:21pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Brandon Kelly is an ExpressionEngine add-on developer, responsible for the extremely popular <a href="http://brandon-kelly.com/fieldframe">FieldFrame</a> and <a href="http://brandon-kelly.com/playa">Playa</a> extensions. He spoke on the importance of commerciality in add-on development.</p> <p>You can watch a <a href="http://vimeo.com/7561777">video of Brandon’s talk</a> on Vimeo.</p> <h2>On commercial add-ons</h2> <ul> <li>Got into ExpressionEngine at the beginning of 2008, releasing <a href="http://brandon-kelly.com/playa">Playa</a> in April 08 (it won <a href="http://devot-ee.com/articles/item/first-annual-academee-awards/">Devot:ee extension of the year</a>). <a href="http://brandon-kelly.com/gypsy">Gypsy</a> was released in December 2008, and <a href="http://brandon-kelly.com/fieldframe">FieldFrame</a> in March 2009</li> <li>Supporting and working on these add-ons was starting to feel more like a job</li> <li>Decided to charge for <a href="http://brandon-kelly.com/playa">Playa 2</a> - $69 seemed like a good number to choose ;)</li> <li>Released <a href="http://brandon-kelly.com/wygwam">Wygwam</a> for $29 in September 2009</li> <li>Making enough money now to support myself, so going full-time freelance at the end of 2009</li> <li>There are lots of free add-ons; we need to change this. Only really simple things should be free</li> <li>It pays to sell. Maybe this is a unique siutation to EE; WordPress users won’t pay for anything</li> <li>Get paid because you deserve it - you’re never done when you release a popular add-on</li> <li>It is easier to support paid add-ons - there are less but better users, more knowledgeable requests, and you feel more obliged to help</li> <li>Pricing: Wait until you’re finished before setting a price. Play customer - you’re picking a price that the customer will want to pay</li> <li>Effort != Value. Find a price point that feels right</li> <li>Marketing: an entry on <a href="http://devot-ee.com/">Devot:ee</a> and a <a href="http://expressionengine.com/forums/viewcategory/35/">forum post</a> might be fine for free add-ons, as someone else will try it and talk about it more. But you can’t do this with paid add-ons; you need to put something together for your users. Be excited! If you’re not, what do you need to change to have a product you are really excited about</li> <li>Playa is a great example for how to set up a site to sell an add-on</li> <li>Buy advertising on EE fansites</li> </ul> <h2>Q&A</h2> <p><strong>Ever had any issues with piracy?</strong><br /> Not bothered - the time needed to combat it is more than the time stolen in support.</p> <p><strong>Leslie Camacho: What do you want EllisLab to do for add-on developers?</strong><br /> Would be nice to be able to advertise add-ons on the official site, but ultimately it’s up to the individual developer to market their add-ons themselves.</p> <p><strong>Why make Wygwam?</strong><br /> I received several requests to make a WYSIWYG editor for FieldFrame. Wygwam represents the first time I’ve made an add-on that wasn’t to solve my own problem.</p> <p><strong>How do you sell online?</strong><br /> Using a hacked version of <a href="http://expressionengine.com/downloads/details/simple_commerce_module/">Simple Commerce</a> module.</p> <p><strong>What do you think about an Add-On Store?</strong><br /> Would be good, maybe. But it would need good quality control.</p> <p><strong>How long do you spend on support?</strong><br /> About 10-15 hours per week.</p> <p><strong>What happens if you decide to give up?</strong><br /> One of the benefits of selling add-ons is that you don’t want to give up. But probably another commercial developer would take over my add-ons.</p> <p><strong>Will you accept commissions from agencies?</strong><br /> Possibly, but I have a big backlog of ideas already.</p> <p><strong>How do you develop?</strong><br /> Frontend first - HTML, CSS, and JavaScript - before looking at the backend.</p> <p><strong>Any plans to integrate add-ons that compete?</strong><br /> No - competition is a good thing. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/veerle.jpg" id="article_image" alt=""> <div id="content"> <h1>Veerle Pieters - Designing and Using The New EE 2.0 Interface</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C6/design">Design</a>, <a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>5:16pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Veerle is a highly-respected designer and <a href="http://veerle.duoh.com/">blogger</a>, and runs <a href="http://duoh.com/">Duoh!</a> with her husband Geert Leyseele.</p> <p>Watch <a href="http://vimeo.com/7556343">Veerle’s talk on Vimeo</a>.</p> <h2>The Design Process</h2> <ul> <li>I was asked to design the new EE 2.0 interface</li> <li>The brief: tabbed menu, the ability to remove and add tabs, save space, make it more professional and less bloggy, fluid layout, smooth edges and softness, customisable GUI, inline demos, and user shortcuts</li> <li>The design process: I was thinking in terms of tasks and levels. Keep it simple. It is better to start designing for beginner users, then the UI can be adapted for experts (rather than the other way around). The current EE Control Panel is overwhelming with options and features</li> <li>Thinking about IA rather than design</li> <li>Screenshots demonstrating iterations on the CP homepage, admin page, file upload preferences, and templates page</li> <li>The Publish page will have a “Writing Mode” - a lightbox that covers the entire page, hiding all non-writing tools</li> <li>Delivered the PSD files to EllisLab and thought the job was done. But then I decided to make a more sombre, grey theme with hot pink higlights. It was eventually chosen as the default for EE 2.0</li> <li>If you use the highlight colour for every clickable element, there is no hierarchy</li> <li>Still talking to EllisLab to finalise design touches - correct usage of highlight colour, rounded CSS3 corners, transparent PNGs, typography, spacing</li> </ul> <h2>Q&A</h2> <p><strong>What about IE6 support?</strong><br /> (Derek Allard) IE6 is not officially supported for the Control Panel. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/allard.jpg" id="article_image" alt=""> <div id="content"> <h1>Derek Allard - Standing On The Shoulders Of Giants</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>5:13pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Derek Allard is EllisLab’s Technology Architect, and discussed how community shapes development at EllisLab.</p> <p>Download the slides of Derek’s talk here (PDF): <a href="http://www.derekallard.com/img/post_resources/eeci2009_derek_allard_slides.pdf">eeci2009_derek_allard_slides.pdf</a>.</p> <h2>EllisLab’s Development Process</h2> <ul> <li>Fell into teaching about web technology; spent 10 years freelancing and teaching</li> <li>How did we get the idea for Image Editor? EE 2.0 was supposed to be feature-neutral, but we’re trying to make EE work the way you work. Feature ideas come from the developers, the staff, blogs, but most often from <a href="http://expressionengine.com/forums/">the forums</a>. We need compelling user-stories to justify new features, and they need to fit into our vision for EE</li> <li>We use <a href="http://subversion.tigris.org/">Subversion</a>, but have experimented with <a href="http://git-scm.com/">Git</a>. There are eight people contributing to the EE codebase now</li> <li>EllisLab have adopted the <a href="http://en.wikipedia.org/wiki/Scrum_%28development%29">Scrum methodology</a> to run development; they work from a priority list, assign time estimates (using the <a href="http://www.planningpoker.com/">PlanningPoker site</a> to compare blind estimates from developers); tasks are assigned to whoever wants to work on it</li> </ul> <h2>EE 2.0’s Image Editor</h2> <ul> <li>For Image Editing, we looked at other implementations, particularly non-web - EE 2.0 was heavily influenced by Mac OSX</li> <li>Live Demo: the new Image Editor features multiple upload directories, Quick Look-style popups, multi-select rows with the keyboard, download multiple files as a ZIP archive, auto-update the UI with no page reload, crop/resize/rotate/flip tools. We’ll be adding other tools like watermarking eventually</li> <li>Needed to integrate it into the Publish page - inspired by CoverFlow, initially I created an animated popup at the bottom of the screen. EPIC FAIL - unintuitive, set unrealistic expectations, so it was scrapped</li> <li>Came up with a much better interface. Work within constraints of bandwidth, thumbnails, natural flow, needed to work with keyboard navigation</li> <li>Live Demo: Publish page integration features paging, only loads images that are visible on the screen, caches thumbs, uses a custom File fieldtype - <a href="http://brandon-kelly.com/fieldframe">FieldFrame</a> is an official part of EE 2.0</li> <li>Extensions will be packaged in their own folders (language, views, etc. all in the same place)</li> <li>Release and Review process - are we happy, is the community happy? All aspects of EE are under this scrutiny</li> </ul> <h2>Q&A</h2> <p><strong>Is there edit history for images?</strong><br /> No, edits are destructive.</p> <p><strong>Can we upload multiple files?</strong><br /> Will be able to upload a zip archive of files, but not multiple files at once. There are security implications with using a Flash uploader to do that.</p> <p><strong>Is there any way to store data with image files (e.g. copyright)?</strong><br /> No. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/colly.jpg" id="article_image" alt=""> <div id="content"> <h1>Simon Collison - Five Years Of Quiet Revolution</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>5:10pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Simon Collison is the Creative Director of <a href="http://erskinedesign.com/">Erskine Design</a>, and discussed his personal history of using ExpressionEngine.</p> <p>Watch or download Simon’s slides from <a href="http://www.slideshare.net/collylogic/ee-five-years-of-quiet-revolution">Slideshare</a>.</p> <h2>My EE History</h2> <ul> <li>ExpressionEngine lets us meet wishlists from clients. As a tool it creates possibilities</li> <li>Background is from building static sites, then using <a href="http://mambo-foundation.org/">Mambo</a> and <a href="http://www.movabletype.org/">MovableType</a> (“crap”)</li> <li>Moving to a dynamic, database-driven site for the first time is exciting</li> <li>Became a designer at <a href="http://www.agenzia.co.uk/">Agenzia</a>, using and hacking pMachine a lot</li> <li>Sold the use of EE 1.x for the <a href="http://www.colly.com/comments/the_libertines_new_site_version_1/">Libertines website</a> on the strength of the possibility for community interaction</li> <li>As EE was developed, the tools we needed started to come out in each release. EllisLab were listening</li> <li>Convinced <a href="http://www.friendsofed.com/">Friends of ED</a> to include ExpressionEngine in the <a href="http://www.friendsofed.com/book.html?isbn=1590595815">Blog Standards Solutions</a> book</li> <li>Agencies and individuals such as <a href="http://www.solspace.com/">Solspace</a> and <a href="http://docs.markhuot.com/">Mark Huot</a> started to use it as the backbone of their work</li> <li>Jamie Pittock launched the first EE fansite, <a href="http://jambor-ee.com/">Jambor-ee</a>, and Mike Boyink’s <a href="http://train-ee.com/">Train-EE</a> was providing tutorials. We started to have places other than the official forums where the community could share their knowledge</li> <li>The <a href="http://www.frieze.com/magazine/">Frieze magazine</a> project was a big test of EE; sixteen years of magazine archives, complex content models, and demonstrated the power of the <a href="http://expressionengine.com/downloads/details/multiple_site_manager/">Multiple Site Manager</a> module</li> <li><a href="http://eeinsider.com/">EEInsider</a> and <a href="http://devot-ee.com/">Devot:ee</a> appeared to share more community information</li> <li>Some add-ons become indispensable - Erskine need <a href="http://brandon-kelly.com/playa">Playa</a> and other commercial add-ons in their work</li> <li>When building a website, it’s wrong to be limited by the technology you use. With EE, we can design sites with an awareness that we can make it happen</li> <li>The ability to (re)design the admin interface ourselves is important</li> <li>We are building our own Ad Server module</li> <li>EllisLab hired Erskine Design to design and develop the demo site that will be included with 2.0</li> <li>The tools coming out in EE 2.0 are what we’ve been waiting for, but we need to spend time with 2.0 before we’ll be comfortable using it for client work</li> </ul> <h2>The future of ExpressionEngine</h2> <p>The future of EE should be to meet the needs of developers and clients. Simon covered the points he believes EE should consider as it grows past the 2.0 milestone.</p> <ul> <li>Adopt common developer methods</li> <li>Have robust first-party modules</li> <li>Provide on-going support for vital add-ons</li> <li>Enable development staging and delivery</li> <li>Provide Un-<a href="http://expressionengine.com/downloads/details/simple_commerce_module/">Simple Commerce</a>!</li> <li>Reintroduce the Advisory Board</li> <li>We need more demos and better example sites</li> </ul> <p>“The quiet revolution is over. If we work smart as a community, we’re in for a great ride.” </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/leslie.jpg" id="article_image" alt=""> <div id="content"> <h1>Leslie Camacho - Foundations: ExpressionEngine 2.0</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>5:01pm <i>on</i> Monday 26th October, 2009</dd> </dl> <p>Leslie Camacho, the President of EllisLab, described the journey to EE 2.0.</p> <p>You can watch or download Leslie’s keynote presentation at <a href="http://www.vimeo.com/7260725">Vimeo</a>, and his slides can be found on <a href="http://www.slideshare.net/lesliecamacho/eeci-2009-keynote">Slideshare</a>.</p> <h2>The Journey</h2> <ul> <li>This week brings the cone of silence to an end, and sets the foundation for the next 5-6 years</li> <li>The original pMachine Pro site was built by Rick Ellis for Nancy Sinatra, and ran on PHP3</li> <li>The community that grew up around pMachine Pro was using it as a CMS, not as a blogging tool</li> <li>The EllisLab team all come from a freelance background; it’s very much a tool “by web developers, for web developers”</li> <li>ExpressionEngine has never been called a CMS internally; we call it a “web publishing platform”</li> <li>We underestimated the amount of work 2.0 would take; version 1.6.8 has 168,000+ lines of code and hundred of add-ons</li> <li>Some example sites running EE: <a href="http://www.vodafonemobileclicks.com/">Vodafone Mobile Clicks</a>, <a href="http://seedmagazine.com/">SEED</a>, <a href="http://www.alistapart.com/">A List Apart</a>, <a href="http://www.bmi.com/">BMI Music</a>, <a href="http://change.gov/">Change.gov</a>, <a href="http://www.frieze.com/magazine/">Frieze magazine</a>, <a href="http://www.leiden.edu/">Leiden University</a></li> <li>These aren’t websites, they are custom web applications. Our CMS needs to bridge with other solutions, tight integration is a necessity. EE is used as a framework</li> <li>Success for web developers means the ability to deliver custom web applications. The line between website and web application is disappearing</li> <li>Foundation > Features. EE 2.0’s foundation is that it is the best commercial CMS, proven in the market, and <a href="http://codeigniter.com/">CodeIgniter</a> is a highly-praised framework (Rasmus Lerdorf, inventor of PHP, says it is the best)</li> <li>So EE + CI = next generation web publishing</li> </ul> <h2>ExpressionEngine 2.0</h2> <ul> <li>EE 2.0 has over 50 new features, a new UI, image editing and a file manager</li> <li>EE 2.1 will return to the normal EllisLab development cycle, and will be a performance/stability/security release</li> <li>Pricing: $149 non-commercial license, $299 commercial license, $50 to upgrade from 1.6.3+, and a $99 freelancer license for up to 5-man web shops to use on their own sites</li> <li>Also introducing corporate licensing and support</li> <li>1.6.8 will be available to download with every 2.0 license</li> <li>Via a video clip of CTO Derek Jones: 2.0 will have custom fieldtypes, an iPhone control panel, and be released on December the 1st 2009</li> <li>An exclusive look at EE 2.0 will start on <a href="http://eeinsider.com/">EEInsider</a> on Monday 26th October</li> </ul> <h2>Q&A</h2> <p><strong>Will modules in 2.0 just be able to make calls directly into the CodeIgniter API/modules?</strong><br /> (Derek Allard) Yes.</p> <p><strong>How much will <a href="http://expressionengine.com/downloads/details/multiple_site_manager/">Multiple Site Manager</a> cost?</strong><br /> Haven’t yet decided for MSM. Corporate license will be expensive. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/jquery.jpg" id="article_image" alt=""> <div id="date">Oct <span>24</span></div> <div id="content"> <h1>jQuery for the Control Panel Considered Harmful</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a>, <a href="http://v4.thewatchmakerproject.com/category/C14/javascript">JavaScript</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>10:55pm <i>on</i> Saturday 24th October, 2009</dd> </dl> <p>Okay, it’s not actually harmful—in fact it’s rather awesome—but you’ll not get any blog traffic without a provocative title, right? What it can be is a pain-in-the-ass when working offline due to the default settings.</p> <p>The <a href="http://www.ngenworks.com/software/ee/cp_jquery/">jQuery for the Control Panel</a> extension is not a first-party extension (it was created by the clever folks at <a href="http://www.ngenworks.com/">nGen Works</a>), but it does come bundled with ExpressionEngine and is invaluable (and often a requirement) for other add-ons. Unfortunately, the extension’s default settings are to load the jQuery library and UI from <a href="http://code.google.com/apis/ajaxlibs/">Google’s centralised repository for JavaScript libraries</a>; this means that if you don’t have a working internet connection—you’re working on the train or a plane, say, or trying to perform a live code demo at a tech conference with patchy wifi—you’ll get nothing but a spinning icon and no JavaScript.</p> <h2>Pros and Cons</h2> <p>Loading code from Google’s servers obviously has some fantastic advantages. The response time is likely to be super-fast with 100% uptime; it’s a different domain to the rest of your site, so <a href="http://www.websiteoptimization.com/speed/tweak/parallel/">downloads can happen in parallel</a>; and if the user has visited a different site using the same library they will have the file cached, speeding up your overall load speed.</p> <p>But this is the Control Panel we’re talking about! Most of the benefits listed above are irrelevant, particularly if your CP admin team is a small one (indeed, for many sites it may just be one individual). And for development, where you may often be working offline, it can be crucial to have jQuery working properly in all environments.</p> <p>Therefore I recommend that, when installing jQuery for the Control Panel, you also:</p> <ol> <li>Download the latest version of jQuery core and UI from the <a href="http://jquery.com/">official jQuery website</a> (zipped or not is up to you, depending on how often you find yourself stepping through JavaScript code at runtime)</li> <li>Change the Settings for the extension to point to your local files</li> </ol> <p>If you are also using jQuery on your website front-end, you can even just point the extension to the front-end’s file (for example, mine lives at <strong>/j/jquery.js</strong>—save those extra characters where you can!)</p> <p>Now you can work on the train, on a plane, or in a blackout—or run a live demo of ExpressionEngine while hundreds of geeks hose the wifi connection—safe in the knowledge that jQuery is always going to load when and where you want it. Just don’t forget to update it whenever a stable new version is released.</p> <p>I believe EllisLab should consider bundling the latest version of jQuery within the .zip of EE (maybe in the <strong>cp_themes</strong> folder?) and default the extension settings to point to that file instead of Google.</p> <h2>Retain the distributed advantage</h2> <p>There are ways that you can host your own JavaScript library but still retain (most of) the advantages I mentioned above when using Google’s repository. I can’t help you with Google’s uptime (but what does that matter if your own site is down? All you need to worry about is your own uptime, really) but the other benefits are easy enough to duplicate.</p> <ul> <li>Serve your site assets—which might include images and stylesheets as well as your scripts—from a different subdomain on your own site, e.g. <strong>assets.example.com</strong>. It’s easy enough to configure your server to point the subdomain at the same location as the rest of the site, but you get the benefit of parallel downloads.</li> <li>Use Stephen Lewis’ <a href="http://www.experienceinternet.co.uk/resources/details/sl-combinator/">SL_Combinator extension</a> to minify, combine and zip your scripts (and stylesheets) for the front-end site. The result is one single, cacheable file for your users, and you can still refer directly to the jQuery library from the back-end.</li> </ul> <h3>Summary</h3> <p>I hope this helps you avoid the annoyances of interrupted work or embarrassing beachballing on stage if you’re trying to work with jQuery as part of the ExpressionEngine Control Panel. It’s a fantastic library and extension; if it were not for this one little issue it would be perfect. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/update.jpg" id="article_image" alt=""> <div id="date">Aug <span>22</span></div> <div id="content"> <h1>How to update ExpressionEngine when your system folder is outside the web root</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>4:14pm <i>on</i> Saturday 22nd August, 2009</dd> </dl> <p>While they make it <a href="http://expressionengine.com/docs/installation/masked_cp_access.html">possible for you to move your main ExpressionEngine installation folder outside of the web root</a>, EllisLab have neglected to allow for that possibility in their update scripts. This article shows you how to fix it with a couple of simple edits.</p> <p>Given that there is even <a href="http://expressionengine.com/blog/entry/web_security_is_a_three_edged_sword/" title="Web Security is a Three Edged Sword by Derek Jones">a blog entry on the EE site on the topic</a>, you might have thought it would be accounted for in the version update script packaged with each new version. Unfortunately though <a href="http://expressionengine.com/docs/installation/update.html">the update instructions</a> and the script itself ignore the possibility that you have moved your <code>/system/</code> folder outside of the web root.</p> <h2>How to update EE, revised</h2> <p>First, ignore the instruction to copy <code>system/update.php</code> into your existing <code>/system/</code> folder; instead, copy it into your web root folder (where your <code>admin.php</code> and <code>path.php</code> files are). It is now reachable at <strong>www.example.com/update.php</strong> - but it doesn’t work because the paths are wrong.</p> <h3>Editing update.php</h3> <p>Open <code>update.php</code> in your text editor. We are going to import the path information used by the rest of the site and update the paths needed for the update to run.</p> <p>Add this line to the start of the file (beneath the copyright message):</p> <pre class="code"> require_once('./path.php'); </pre> <p>Next, at the top of the file there are a series of definitions:</p> <pre class="code"> define('EXT', '.'.$path['extension']); define('PATH', './'); define('PATH_DB', './db/'); define('PATH_CORE', './core/'); define('PATH_LANG', './language/'); define('PATH_MOD', './modules/'); define('PATH_EXT', './extensions/'); define('PATH_PI', './plugins/'); define('CONFIG_FILE', 'config'.EXT); </pre> <p>Let’s update them to use the correct path information:</p> <pre class="code"> define('EXT', '.'.$path['extension']); define('PATH', $system_path); define('PATH_DB', $system_path . 'db/'); define('PATH_CORE', $system_path . 'core/'); define('PATH_LANG', $system_path . 'language/'); define('PATH_MOD', $system_path . 'modules/'); define('PATH_EXT', $system_path . 'extensions/'); define('PATH_PI', $system_path . 'plugins/'); define('CONFIG_FILE', $system_path . 'config'.EXT); </pre> <p>We’re almost done, but there’s just one more place where the path is hardcoded and needs to be fixed. In the <code>Update()</code> class method <code>update_manager()</code>, we need to use the path information one more time. Change these lines:</p> <pre class="code"> function update_manager() { global $DB; </pre> <p>Here's the revised version:</p> <pre class="code"> function update_manager() { global $DB, $system_path; $this->update_dir = $system_path . 'updates/'; </pre> <p>We’re just overriding the path to the update directory with the correct path.</p> <p>Now load the update script at <strong>www.example.com/update.php</strong> to run the update with no problems, despite your <code>/system/</code> root not being where it <em>‘should’</em> be.</p> <h2>This should be in the EE trunk</h2> <p>Hopefully EllisLab will eventually make this hacking unnecessary and incorporate these changes into the official release, but in the meantime if you’re a security-conscious developer I hope this was useful. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/typewriter.jpg" id="article_image" alt=""> <div id="date">Jun <span>17</span></div> <div id="content"> <h1>ExpressionEngine: Scrippets for FieldFrame, too</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a>, <a href="http://v4.thewatchmakerproject.com/category/C13/film">Film</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>8:44pm <i>on</i> Wednesday 17th June, 2009</dd> </dl> <p>Following yesterday’s work to convert the Scrippets plugin for ExpressionEngine, it was simple to turn it into a new field type for <a href="http://brandon-kelly.com/apps/fieldframe">Brandon Kelly’s excellent FieldFrame extension</a>.</p> <p>If you’ve not used FieldFrame before, you are missing out on some serious EE goodness. It extends the default set of field types, including many straightforward fields—checkboxes, radio buttons, etc.—plus many, many more contributed by other developers.</p> <h2>And now there’s one more</h2> <p>The Scrippet field type works in exactly the same way as <a href="http://www.thewatchmakerproject.com/blog/new-expressionengine-plugin-scrippet/">the standalone plugin</a>, except that you enter your plaintext script content in its own separate field in the Control Panel.</p> <p>Then you simply refer to your field (by whatever name you have given it in Custom Fields) in your template, and the formatting is automatically applied:</p> <pre class="code"> {exp:weblog:entries weblog="blog"} <h2>{title}</h2> {script_extract} {/exp:weblog:entries} </pre> <p>The parameters are the same as for the <code>{exp:scrippet}</code> plugin (see <a href="http://www.thewatchmakerproject.com/blog/new-expressionengine-plugin-scrippet/">my previous entry</a> for details), and you also need to either link to or include the <abbr title="Cascading Style Sheets">CSS</abbr> from <code>scrippets.css</code> as well.</p> <p>It works as part of the <a href="http://wiki.github.com/brandonkelly/bk.fieldframe.ee_addon/ff-matrix">FF Matrix</a> fieldtype as well, so you can post tables of script snippets to your heart’s content. Grab the files from GitHub as per normal.</p> <div class="github"> <h3><a href="http://github.com/matthewpennell/mgp.ee_scrippet_fieldframe.ee_addon/">Visit GitHub to download files</a></h3> </div> <p><strong>What is GitHub?</strong> GitHub is a web application that uses the version control software Git to allow its members to manage their code online. I am hosting the files for this article there so that any bugfixes or improvements I make can be found in one central location. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/typewriter.jpg" id="article_image" alt=""> <div id="date">Jun <span>16</span></div> <div id="content"> <h1>New ExpressionEngine Plugin: Scrippet</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a>, <a href="http://v4.thewatchmakerproject.com/category/C13/film">Film</a>, <a href="http://v4.thewatchmakerproject.com/category/C12/writing">Writing</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>6:27pm <i>on</i> Tuesday 16th June, 2009</dd> </dl> <p>Here’s a little piece of formatting niceness that will be handy for anyone with an interest in film or scriptwriting. The Scrippet plugin converts your plain text screenplay extracts into nicely-formatted script blocks.</p> <p>Based on <a href="http://johnaugust.com/archives/2008/scrippets-php-and-a-call-to-coders">an original idea</a> by screenwriter <a href="http://www.imdb.com/name/nm0041864/" title="John August on IMDb">John August</a>, most of the work on <a href="http://scrippets.org/">Scrippets</a> was done by <a href="http://equinox-of-insanity.com/">Nima Yousefi</a> for the original Wordpress plugin. I’ve simply taken that code and adapted it for use in ExpressionEngine.</p> <div class="update"><strong>Update 17/06:</strong> I have now also converted the Scrippet formatting into a new fieldtype for Brandon Kelly’s FieldFrame extension, so you can enter scripts directly into the Publish page. See <a href="http://www.thewatchmakerproject.com/blog/expressionengine-scrippets-for-fieldframe-too/">this blog entry</a> for full details.</div> <h2>Installation and Usage</h2><p> </p> <p>To install the Scrippet plugin, grab the plugin and stylesheet from <a href="http://github.com/matthewpennell/mgp.ee_scrippet.ee_addon/">my GitHub repository</a>. Copy the <code>pi.scrippet.php</code> file into your <b>/plugins</b> folder.</p> <p>Unfortunately, ExpressionEngine doesn’t offer an easy way to dynamically load additional stylesheets, so for now you can either attach the <code>scrippets.css</code> stylesheet to your template, or copy-and-paste the <abbr title="Cascading Style Sheets">CSS</abbr> rules from that file into your existing site stylesheet.</p> <p>To use the plugin, wrap your unformatted screenplay extract in <code>{exp:scrippet}{/exp:scrippet}</code> tags:</p> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/scrippet.gif" class="col five" alt="Formatted scene" title="The output of the exp:scrippet block, formatted according to the standard screenplay rules"></p> <pre class="code"> {exp:scrippet} INT. CARGO LOCK The Queen spins at the sound of door motors behind her. The parting doors REVEAL an inhuman silhouette standing there. Ripley steps out, WEARING TWO TONS OF HARDENED STEEL. THE POWER LOADER. Like medieval armor with the power of a bulldozer. She takes a step…the massive foot CRASH-CLANGS to the deck. She takes another, advancing. Ripley's expression is one you hope you'll never see… Hell hath no fury like that of a mother protecting her child and that primal, murderous rage surges through her now, banishing all fear. RIPLEY Get away from her, you bitch! {/exp:scrippet} </pre> <h3>Parameters</h3> <p>There are a few optional parameters available to use with the <code>{exp:scrippets}</code> tag:</p> <ul> <li><code>width</code> - Sets the width (in pixels) of your scrippet block</li> <li><code>bg_color</code> - Sets the background colour of the block; you can use hex values, colour keywords, or RGBa values</li> <li><code>text_color</code> - Sets the text colour; possible values as per <code>bg_color</code></li> <li><code>alignment</code> - Valid values are <code>left</code> or <code>center</code>; blocks with <code>alignment=“center”</code> will be centered on the page</li> </ul> <p>The default appearance of the scrippet blocks is black text on a pale yellow background, 400 pixels wide.</p> <h3>Formatting options</h3> <p>Styles are applied to the text according to how it is formatted:</p> <ul> <li><strong>Scene headings</strong> start with either “INT”, “EXT” or “EST” and are all capitalised</li> <li><strong>Transitions</strong> end with a colon (e.g. “CUT TO:”) or can be a few hard-coded other options (e.g. “FADE TO BLACK”)</li> <li><strong>Characters</strong> will be in ALL CAPS followed by a single new-line</li> <li><strong>Parantheticals</strong> will be wrapped in parentheses, obviously</li> <li><strong>Dialogue</strong> comes straight after a character or paranthetical element</li> <li>and <strong>Action</strong> is anything that doesn’t fall into any of the above categories</li> </ul> <p>You can also include some additional formatting by using standard Textile markup for <code>**bold text**</code>, <code>*italicised text*</code> or <code>_underlined text_</code>.</p> <h2>Future developments</h2> <p>Another obvious use-case for this would be as a new field type for Brandon Kelly’s <a href="http://brandon-kelly.com/apps/fieldframe">FieldFrame extension</a>, and when I have a few spare minutes I’ll throw that together too.</p> <div class="github"> <h3><a href="http://github.com/matthewpennell/mgp.ee_scrippet.ee_addon/">Visit GitHub to download files</a></h3> </div> <p><strong>What is GitHub?</strong> GitHub is a web application that uses the version control software Git to allow its members to manage their code online. I am hosting the files for this article there so that any bugfixes or improvements I make can be found in one central location. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/ftpssh.jpg" id="article_image" alt=""> <div id="date">Jun <span>12</span></div> <div id="content"> <h1>Review: FTPOnTheGo and TouchTerm SSH for iPhone</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C16/freelancing">Freelancing</a>, <a href="http://v4.thewatchmakerproject.com/category/C18/iphone">iPhone</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>10:51pm <i>on</i> Friday 12th June, 2009</dd> </dl> <p>During our last family holiday, any serious client website issues meant a quick trip to the nearest town and an hour in the public library to use the creaky old PC they helpfully provide for vacationing web designers. This year, though, I can work directly on the server with my two new favourite iPhone apps: <a href="http://www.ftponthego.com/">FTPOnTheGo</a> and <a href="http://www.jbrink.net/touchterm/">TouchTerm SSH</a>.</p> <h2>FTPOnTheGo</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/ftponthego.png" class="col six" alt="FTPOnTheGo screenshots" title="Browsing folders and editing files with the iPhone's FTPOnTheGo application"></p> <p>The file handling capabilities of the iPhone have always been a little underwhelming, making the killer feature of <a href="http://www.ftponthego.com/">FTPOnTheGo</a>—downloading, editing, and uploading files—that much more impressive. But let’s start at the beginning.</p> <p>The app sensibly opts to use the standard iPhone <acronym title="User Interface">UI</acronym> library rather than introduce their own graphical lexicon, so it all feels very natural and the learning curve is shallow. An unexpected addition is the presence of short YouTube “how to” videos available right in the app, which serve to introduce the basics to new users.</p> <p>Simply provide a server address, username and password (or select from your bookmarked connections) to connect to a server either by <acronym title="File Transfer Protocol">FTP</acronym> or <acronym title="Secure File Transfer Protocol">SFTP</acronym>. Once connected, you can browse through the files and folders; sort by name, size or date; upload pictures from your phone; create new files or folders; and rename, delete, move or save existing files. It’s also possible to use your iPhone as a Web or FTP server and share files from it, although I haven’t needed to use that feature yet.</p> <p>But the real lifesaver for any web developer away from his desk is the file editing. Click a file then click the ‘Edit’ button to launch a basic text editor with support for Find/Replace, encoding changes, and usable in either portrait or landscape mode. When you’re finished editing, simply click ‘Save’ to upload the file back to the server.</p> <p>While it’s obviously not the optimal device on which to code (and I’d like to see a more customised keyboard to make it easier to access commonly used keys such as angle brackets, plus the obvious enhancement of syntax highlighting) the text size is small enough to fit a sensible amount of text on the screen, and the ‘go to line number’ feature makes navigating large files easy enough.</p> <p>The app is also chock-full of user settings, including a choice of folder icons (Vista, XP, Mac or “Old School”), fine control over the font used for file editing, and several granular security options. You can also set a master password for the whole app to protect your login information.</p> <h2>TouchTerm SSH</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/touchtermssh.png" class="col five" alt="TouchTerm SSH screenshots" title="The keyboard and main keys are displayed over the text entry area in TouchTerm SSH"></p> <p>Of course sometimes simple FTP access isn’t enough to solve a server problem—what if you need to stop or start a service, or… well, my ssh-fu doesn’t extend to much beyond that, but for those who need it, the ability to connect directly to your server and run commands remotely might be a lifesaver.</p> <p>There are a handful of SSH apps available on the iTunes App Store, but luckily the best is also the cheapest. <a href="http://www.jbrink.net/touchterm/">TouchTerm SSH</a> allows you to connect through either a stored connection or “One-Time Connection,” and also offers the option to either save or forget passwords. It also includes management of key pairs if you prefer to use those rather than passwords.</p> <p>Connecting presents you with the standard monospaced-font-on-black Terminal/Console interface, with some neat iPhone-specific features. As you might expect the handset can be rotated to use in either landscape or portrait mode. Keys that you often need access to—Ctrl, Alt, Tab, Esc, the arrow keys—are presented along the top of the screen, or can be displayed permanently as a transparent overlay, allowing you to see what you’re typing as you work. The keyboard also works in the same way, and is surprisingly usable even with multiple lines of text behind it.</p> <p>There’s a bit of a latency problem while typing (as there can sometimes be over <acronym title="Secure Shell">SSH</acronym> normally), but there’s also a fantastic setting that allows you to buffer your command(s) in a standard iPhone textbox before sending the whole line over the wire. It also maintains a history of the text you have sent, so accessing previous complicated commands is a doddle.</p> <p>There’s not much more that can be said about an <acronym title="Secure Shell">SSH</acronym> client, except to mention that TouchTerm also boasts an impressive array of settings, including fine control over the appearance of the various elements, and security/encoding settings.</p> <h2>These apps are great value for money</h2> <p><a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=286623227&mt=8" title="TouchTerm SSH on the iTunes App Store">TouchTerm SSH</a> is only £0.60 ($0.99 on the US store), which amazes me considering the kind of people who are likely to need a fully featured <acronym title="Secure Shell">SSH</acronym> app. <a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=286479936&mt=8" title="FTPOnTheGo on the iTunes App Store">FTPOnTheGo</a> is a little pricier at £3.99 (probably $5.99 in the <acronym title="United States">US</acronym>, at a guess), but for the peace of mind they bring when away from home they are definitely recommended for any iPhone-touting web developer. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/speed.jpg" id="article_image" alt=""> <div id="date">May <span>08</span></div> <div id="content"> <h1>Benchmarking Array Indexes for String Comparison</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C17/php">PHP</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>9:59pm <i>on</i> Friday 8th May, 2009</dd> </dl> <p>I’ve been doing some work recently on a custom search engine and, as you might imagine, that involves a fair amount of string comparison and manipulation. When the first iteration of the search module was returning results after eleven minutes I started looking seriously at <acronym title="PHP: Hypertext Preprocessor">PHP</acronym> and MySQL optimisations; queries are down to a few seconds now, but there are still savings to be made, and this week I’ve been testing the various ways to compare parts of strings.</p> <h2>Reducing Function Calls</h2> <p>My basic goal was to reduce the number of function calls, particularly those within large loops. Everyone knows tricks like setting the length of a loop outside of the actual check statement, and if you’ve read up on any <a href="http://www.phpbench.com/">PHP benchmarking</a> you’ll know that some forms of loops are quicker than others:</p> <pre class="code"> // This is bad for ($x = 0; $x < count($myArray); $i++) { // Do something } // This is better for ($x = 0, $size = count($myArray); $x < $size; $i++) { // Do something } // This is best $x = 0, $size = count($myArray); while ($x < $size) { // Do sometthing $x++; } </pre> <p>So my assumption was that removing function calls equals faster code. My loops were pretty well optimised—what about my string comparisons?</p> <h3>String Comparison Functions</h3> <p>I needed to compare subsections of strings, so I was using a lot of <code>substr()</code>, but I realised that where I knew the position of the start and end of the substring, I could use array indexes instead! So this:</p> <pre class="code"> if (substr($str, 0, 2) === $test) { ... } </pre> <p>Became this:</p> <pre class="code"> if ($str[0] . $str[1] === $test) { ... } </pre> <p>After congratulating myself for discovering this handy shortcut and optimisation trick—getting rid of that function call had to be faster, right?—I decided I should probably check that it was actually the improvement I assumed it was.</p> <h3>Benchmarking Results</h3> <p>The results are actually surprising. In tests, the <code>substr()</code> call is actually <em>faster</em> for strings of three or more letters; using pseudo-array indexes is only really worth doing if you’re comparing at most one or two characters.</p> <p>It surprised me that the concatenation operations were so much slower than the <code>substr()</code> function call (at least 50% slower)—I was really expecting it to be a much faster way of comparing strings.</p> <p>So, the lesson is that array indexes are useful for strings, but only really when you’re comparing a single character (where you can see a drop in execution time of around two-thirds)—otherwise, stick to <code>substr()</code>. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/grace-hopper.jpg" id="article_image" alt=""> <div id="date">Mar <span>24</span></div> <div id="content"> <h1>Ada Lovelace Day: Grace Hopper</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C1/Blogging">Blogging</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>10:34pm <i>on</i> Tuesday 24th March, 2009</dd> </dl> <p>When I signed the pledge for <a href="http://findingada.com/">Ada Lovelace Day</a> and agreed to publish a blog post on an influential woman in technology on March 24th, it seemed like a good idea. Easy enough to achieve, and something I could contribute to, however indirectly, for my daughters.</p> <p>This was a rather rash decision, as it turns out; now on the day itself, I find myself struggling to find a suitable subject.</p> <p>It is not as if I do not know any women working in technology. There are plenty of women that I have met or worked with; off the top of my head, any one of <a href="http://pixelingo.com/" rel="friend colleague">Carolyn</a>, <a href="http://www.disambiguity.com/" rel="friend met">Leisa</a>, <a href="http://www.thatcanadiangirl.co.uk/" rel="friend met colleague">Vero</a>, <a href="http://www.lealea.net/" rel="friend met colleague">Lea</a>, <a href="http://veerle.duoh.com/" rel="contact met colleague">Veerle</a>, <a href="http://veerle.duoh.com/" rel="friend met">Glenda</a> or <a href="http://molly.com/" rel="acquaintance met">Molly</a> would probably make a perfectly good subject. But for me the sticking point is the “in technology” part—being a web designer (or usability person, or content person, or just a web maven in general) just doesn’t feel like it’s really “technology”.</p> <p>So I figured I would buck the trend that has seen people like <a href="http://www.pixeldiva.co.uk/admires/these-women/" rel="friend met colleague">Ann</a> and <a href="http://www.wait-till-i.com/2009/03/24/ada-lovelace-day-women-in-technology-i-admire/" rel="acquaintance colleague">Christian</a> blog about their contemporaries, and instead look back at someone who had an impact in the tech sector when it was in its infancy.</p> <h2>The Mother Of Computers</h2> <p><strong>“Amazing” Grace Hopper</strong> was a maths graduate and teacher at Vassar College in NY. The first woman to ever earn a Ph.D. in Mathematics from Yale, she left her comfortable job during the war to volunteer with the US Navy, and it was there that she made her mark on the future of computing.</p> <p>Hopper was one of the first programmers to work on the new <a href="http://en.wikipedia.org/wiki/Harvard_Mark_I">Harvard IBM Mark I computer</a>, a 50-foot-long behemoth capable of a staggering <em>three calculations per second</em> (!), and after the war she opted to stay on at Harvard and continue working in the nascent programming field. It was while working on the new <a href="http://en.wikipedia.org/wiki/UNIVAC_I">UNIVAC</a> computer that she developed the first ever language compiler, which later became the programming language COBOL. Hopper’s idea was that programs could be written in a language closer to English than machine code or assembly language.</p> <p>Later she drove the implementation of standards for testing computer systems and languages (yay, standards!) that were later adopted and administered by the National Office of Standards and Technology.</p> <p>Aside from the delicious irony of her win as the first “Man of the Year” award from the Data Processing Management Association in 1969, Grace Hopper also has an <a href="http://awards.acm.org/hopper/" title="The Grace Murray Hopper Award for Outstanding Young Computer Professionals">annual award</a>, a <a href="http://en.wikipedia.org/wiki/USS_Hopper_(DDG-70)" title="The USS Hopper, obviously">ship</a>, a <a href="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=Grace+Hopper+Avenue,+Monterey,+California&sll=37.0625,-95.677068&sspn=34.808514,78.046875&ie=UTF8&z=16" title="Grace Hopper Avenue is in Monterey, California">road</a>, a <a href="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=%22grace+murray+hopper+park%22,+arlington,+virginia&sll=39.098095,-76.923523&sspn=1.014605,2.438965&ie=UTF8&ll=38.861382,-77.063577&spn=0.004177,0.009527&t=h&z=17" title="Grace Murray Hopper Park is in Arlington, Virginia">park</a> and a data processing centre named after her. The official advisory council on the recruitment and retention of women at <a href="http://www.microsoft.com/">Microsoft</a> is named “Hoppers” in her honour, and she has been called “The mother of computers”—but, if anyone has heard of her, it is usually because of one particular event that occurred relatively early in her career.</p> <h3>The first computer bug</h3> <p>While working at Harvard on the <a href="http://en.wikipedia.org/wiki/Harvard_Mark_II">IBM Mark II</a>, a moth was found to be stuck in one of the relays that formed part of the machine, causing her to remark that they were “debugging” the system. While it is not certain that the term <em>computer bug</em> is solely attributable to Hopper, she certainly brought the term into popular usage. (<a href="http://en.wikipedia.org/wiki/File:H96566k.jpg">The moth</a> is still on display in the group’s log book at the Smithsonian.)</p> <p>Grace Hopper died in 1992 at the age of 85. Almost until the end of her life, she was active lecturing and speaking at universities and computer seminars on the importance of change. As she said, “the most damaging phrase in the language is ‘We’ve always done it this way.’”</p> <blockquote><p>“Our young people are the future. We must provide for them. We must give them the positive leadership they’re looking for ... You manage things; you lead people.”</p></blockquote> <p>[Sources: <a href="http://en.wikipedia.org/wiki/Grace_Hopper">Wikipedia</a>, <a href="http://www.history.navy.mil/bios/hopper_grace.htm">Biographies in Naval History</a>. Photos from Wikipedia.] </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/6th-st.jpg" id="article_image" alt=""> <div id="date">Mar <span>20</span></div> <div id="content"> <h1>South By South West 2009</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C10/sxsw">SXSW</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>5:01pm <i>on</i> Friday 20th March, 2009</dd> </dl> <p>Thanks to a four-hour layover in Dallas Fort Worth, I’m able to take the opportunity to write up my notes and thoughts on the rest of 2009’s <a href="http://www.sxsw.com/">South By South West</a> while it’s still fairly fresh in my mind. Hopefully a lack of sleep and too much coffee will not overly affect my, uh, you know. That thing. Being good. With words.</p> <h2>Saturday (Day 2)</h2> <p>Friday was a late one after <a href="http://superfluousbanter.org/" rel="friend met colleague">Dan Rubin</a>‘s <a href="http://watchmenmovie.warnerbros.com/">Watchmen</a> outing (despite an automatic knee-jerk reaction to any deviations from the comic book, I actually really enjoyed it; I want to see it again before giving a full review, though). The weather wasn’t great either—cold and rain I have at home, Austin!—but once safely inside the Austin Convention Center, the upgraded infrastructure coped admirably well with the 10,000 attendees’ wifi requirements.</p> <p>The afternoon keynote, by <a href="http://www.zappos.com/" title="You can call them to order pizza!">Zappos</a> <acronym title="Chief Executive Officer">CEO</acronym> Tony Hsieh, was extremely inspiring, although guaranteed to frustrate anyone without a direct line to the people able to really drive the kind of change described by Hsieh and implemented by him at Zappos. The stories he told about how their staff live and breathe the company culture and values, and how the steps that his team have taken to build a brand that will bring happiness, were great, and once the video is up on <acronym title="South By South West">SXSW</acronym> it should be required viewing for company MDs anywhere.</p> <p>The worst panel I saw this year was <em>Designing For Irrational Behaviour</em>, which was oddly pitched between interface design talk and psychology lecture. The self-confessed <a href="http://www.peterwhybrow.com/">tech noob college professor</a> would have been great to listen to in the right context (i.e. college), but really struck a bum note for most of the attendees in the panel; I wasn’t alone in feeling bad for the panelists as their room haemorrhaged people throughout the scheduled hour.</p> <p>I had assumed that <em>Building Your Brand</em> would have been at least a little relevant for someone looking for business brand tips, but instead it was purely focused on social media personal brand management. I seemed to be in the minority by not having a clue who any of the people up on stage were (okay, I know of Loic Le Meur through the <a href="http://LeWeb.net/">LeWeb</a> conference, but by name only), but it was an entertaining panel anyway—not least due to the presence of live <a href="http://search.twitter.com/">Twitter search</a> up on the jumbotron, allowing both those in the audience and around the world to participate and/or trade insults in real-time. I even got to join in—well, you can’t let <a href="http://twitter.com/chrisbrogan" title="Apparently I should know who this is?">someone</a> get away with a statement like “Twitter is the new phone” without <a href="http://twitter.com/matthewpennell/status/1329042275" title="Oops, forgot my parents read my Twitter updates via Facebook…">calling them on it</a>, can you?</p> <h2>Sunday (Day 3)</h2> <p>Whenever I start to feel guilty about sunning myself in Austin on the company tab, I remind myself that I’m voluntarily spending my entire weekend working. It’s 10am on Sunday, but I’m learning about <em>Interface Lessons From Games</em>. Commitment, right? </p> <p>There are some talks that you just know are going to be great, and <a href="http://www.uie.com/" rel="met">Jared Spool</a> never fails to deliver. His <em>Journey To The Center Of Design</em> show, complete with <a href="http://www.flickr.com/photos/stalelife/3363422080/">human bell curves</a> and a bold takeaway (“User Centered Design is dead” according to Jared), was a definite highlight of the conference.</p> <p>I also sat in on the <em>iPhone Development</em> panel, hoping to learn how easy it might be to build a native application. The Objective-C development platform doesn’t look too depressingly complex, and the <acronym title="Integrated Development Environment">IDE</acronym> makes it easy to drag-and-drop interface elements to wire up your app quickly (ah, now I see where <a href="http://280atlas.com/" title="Atlas by 280 North">Atlas</a> comes from!), but it was disappointing to hear that effectively everything they talked about is probably going to become redundant as soon as Apple releases the next version of the <acronym title="Software Development Kit">SDK</acronym>. Still, it’s an area I plan to investigate in the medium term.</p> <p>After failing to get into any of the smaller panels in the afternoon, we ended up listening to <a href="http://garyvaynerchuk.com/">Gary Vaynerchuk</a> do his thing in the large ballroom. I love what the guy does, and completely respect his commitment to his passion, but I don’t think I could deal with him in person every day…</p> <h3>(Some) Geeks (kind of) Love Bowling</h3> <p>My third year at <a href="http://avalonstarevents.com/abx2009/"><acronym title="South By South West">SXSW</acronym> bowling</a> (and I believe its fourth year overall) was substantially more subdued than past events,  with barely half the lanes in use and a much smaller concentration of geeks than last year. It was a pity that it was up against so many other parties that night (including the Facebook and Tumblr parties), and I hope that <a href="http://bryanveloso.com/" rel="friend met colleague">Bryan</a> can rebuild it to its previous heights for next year, as it was always a highlight of the week for me.</p> <h2>Monday (Day 4)</h2> <p>Now in its third year, the <em>Browser Wars</em> session was a frank exchange of views and opinions by representatives of Mozilla, Opera, Chrome and Internet Explorer. The moderator asked some tough questions, particularly of <a href="http://cwilso.com/" rel="contact met">Microsoft’s Chris Wilson</a>, but it was great to hear about the kinds of things that they are thinking about, particularly concerning how the specs get debated and agreed. The <acronym title="Internet Explorer">IE</acronym> discussion continued at the <em><a href="http://www.webstandards.org/"><acronym title="Web Standards Project">WaSP</acronym></a> Annual Meeting</em> where <a href="http://www.easy-designs.net/" rel="colleague">Aaron Gustafson</a> summed up the work that Microsoft have been doing this year concerning version targeting—Craig Cook asked why IE8’s “IE7 compatibility mode” is subtly different from IE7 itself, and apparently they (MS) plan to fix all the bugs still relating to those discrepancies.</p> <p>I had another great lunch at Iron Cactus with the guys from <a href="http://www.ellislab.com/">EllisLab</a> (plus a few other <acronym title="Expression Engine">EE</acronym> enthusiasts), and later <a href="http://www.derekallard.com/" title="The man to talk to aboot EE 2.0" rel="friend met colleague">Derek Allard</a> took us through a demo of <a href="http://www.expressionengine.com/index.php?affiliate=thewatchmakerproject">ExpressionEngine</a> 2.0. All I can say is, wow—it is so much more than just a port of <acronym title="Expression Engine">EE</acronym> 1.6 to the <a href="http://www.codeigniter.com/">CodeIgniter framework</a>. Some of the features they have added (many with great <a href="http://jquery.com/">jQuery</a>-powered interactions, Derek’s been busy!) are going to cut development time in half when you’re setting up that new <acronym title="Expression Engine">EE</acronym> project. I can’t wait until it comes out, and what I’ve seen means I really don’t care what the price uptick ends up being—I want this <acronym title="Content Management System">CMS</acronym>!</p> <p>After most of the regular sessions had ended, <a href="http://www.silverspider.com/" rel="friend met colleague">Alex Jones</a> from <a href="http://www.refreshaustin.org/">Refresh Austin</a> led a Core Conversation on <em>Energising Communities</em>. It was great to have the opportunity to participate as part of a smaller group, and there were some really interesting discussions with people from <a href="http://refreshdenver.org/">Refresh Denver</a> and some <acronym title="United Kingdom">UK</acronym>-based groups too.</p> <h2>Tuesday (Day 5)</h2> <p>If there is one word that sums up <acronym title="South By South West">SXSW</acronym> this year, that word would have to be: <a href="http://www.twitter.com/">Twitter</a>. In virtually every panel, every conversation, and on every corner, Twitter was being heralded as the saviour of the internet. Me? I don’t think it’s <a href="http://en.wikipedia.org/wiki/Jumping_the_shark" title="I don't think I'll ever feel comfortable using the phrase 'nuked the fridge', though">jumped the shark</a> quite yet, but it’s certainly putting on its water-skis.</p> <p>The <a href="http://www.guykawasaki.com/">Guy Kawasaki</a> keynote really didn’t appeal, so instead I went to the <em>Mad Men on Twitter</em> panel, which was really good. I’m a big fan of <a href="http://www.amctv.com/originals/madmen/">Mad Men</a>, and an admirer of what I had always assumed was a carefully managed media campaign on Twitter, so I was really surprised to learn that the people behind the multitude of <a href="http://wearesterlingcooper.com/">Mad Men characters living on the social network</a> have absolutely nothing to do with <span class="caps">AMC</span> or the <acronym title="Public Relations">PR</acronym> firm for the show. Of course, it’s no coincidence that many of the people who spotted the opportunity and value in twittering as their favourite characters work in the PR and marketing industry, but as <a href="http://www.twitter.com/PeggyOlson" rel="contact">@PeggyOlson</a> pointed out it’s still surprising that more production companies (or even writers) aren’t making use of Twitter to extend their brand and character development to a sub-section of fans.</p> <p>Apple’s <a href="http://cookiecrook.com/" title="@cookiecrook on Twitter" rel="contact met colleague">James Craig</a> closed out my final day of the conference with an interesting look at <em>Universal Design</em>, and a reminder that accessibility can often have a much bigger impact than simply making your site or app [more] usable for visitors with disabilities. Nothing new, perhaps, but sometimes you just need reminding that there are many simple steps that you can take to make life easier for people.</p> <h2>Summary</h2> <p>I had yet another great year in Austin; despite the initially poor weather it brightened up eventually, and staying <a href="http://www.pecanstreetlofts.com/" title="Pecan Street Lofts, 30 seconds from the Iron Cactus!">right on 6th St</a> (with <a href="http://boxofchocolates.ca/" title="Derek Featherstone" rel="friend met colleague">Derek</a>, <a href="http://paulstamatiou.com/" title="Paul Stamatiou" rel="friend met colleague">Paul</a> and <a href="http://immike.net/" title="Mike Malone" rel="friend met colleague">Mike</a>) really made for an ideal central location, convenient for both the Convention Center and the parties. Speaking of parties, yet again they were awesome—<a href="http://97bottles.com/">97bottles</a> Happy Hour, South By North West, and the <a href="http://www.mediatemple.net/go/order/?refdom=29digital.net">MediaTemple</a> closing party were chock-full with friends old and new. And I finally made it to a Breakfast with <a href="http://www.dustindiaz.com/" title="Mr Diaz" rel="friend met colleague">Dustin</a> at the <a href="http://www.ihop.com/"><acronym title="International House Of Pancakes">IHOP</acronym></a>, which ticks off another experience on my list of “quintessential American places to visit.”</p> <p>I should also thank <a href="http://interllectual.com/" rel="friend met colleague">Andrea Schwandt-Arbogast</a> for putting up with me for large amounts of the time and hanging out all week—you rock, and I probably won’t show that photograph to too many more people. ;)</p> <p>Roll on SouthBy 2010. [<a href="http://www.flickr.com/photos/lanbui/3363956356/">original photo</a> by Lan Bui] </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/sxsw.jpg" id="article_image" alt=""> <div id="date">Mar <span>16</span></div> <div id="content"> <h1>SXSW 2009, Day 1</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C10/sxsw">SXSW</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>3:05am <i>on</i> Monday 16th March, 2009</dd> </dl> <p>Based on my experience of previous years, I was expecting the Friday of <acronym title="South By South West">SXSW</acronym> to be largely a waste of time—but this year actually featured some great sessions.</p> <h2>Everything you know about web design is wrong</h2> <p><a href="http://www.sapient.com/">Dan Willis of Sapient</a> drew parallels between the dawn of modern cinema (cf. <a href="http://www.imdb.com/title/tt0004972/">Birth of a Nation</a>, probably the only time you’re going to see the Ku Klux Klan at a web conference) and our industry’s slow discovery of the grammar of modern web design.</p> <p>It was largely interesting, and Willis did point to some emerging trends as possible candidates for how things could or should change—random voyeurism, self-aware content, user-created content, ambient awareness and experiential content—but ultimately had no answers. And who couldn’t have told us that the web is different from print?</p> <h2>Unnatural experiments in web design</h2> <p>In the same ballroom, <a href="http://paulannett.co.uk/">Paul Annett</a> from <a href="http://www.clearleft.com/">Clearleft</a> explored some of the cool hidden treasures people are putting into their designs. Starting from FedEx’s hidden arrow and the bear in the Toblerone logo, he ran through a laundry list of interesting techniques in use on the web; <a href="http://silverbackapp.com/">Silverback</a>‘s parallax scrolling backgrounds, <a href="http://www.webleeddesign.com/">We Bleed Design</a>‘s endless scrolling paint stripes, and <a href="http://www.skittles.com/">Skittles’</a> recent social media experimental homepage, among others.</p> <p>His point, ultimately, was that adding hidden treasures to your design can surprise and delight users, and the natural feeling of wanting to share your discovery naturally translates into high visibility and pseudo-viral marketing for your site or product. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/buffalo-billiards.jpg" id="article_image" alt=""> <div id="date">Mar <span>10</span></div> <div id="content"> <h1>Meet me at SXSW</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C10/sxsw">SXSW</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>11:04pm <i>on</i> Tuesday 10th March, 2009</dd> </dl> <p>It’s been entertaining watching normally quiet blogs spring to life this week, as SXSW attendees try to remind the community that they have something worthwhile to say. Here’s one more.</p> <p>In fact I have very little to say about SXSW besides linking to my post from last year about <a href="http://v3.thewatchmakerproject.com/journal/457/how-to-disable-visual-voicemail-on-the-iphone-for-uk-users">how to disable visual voicemail on the iPhone</a>, in case any other UK iPhone owners have forgotten how to do it - and if you see me please come and say hello!</p> <h2>Party harty</h2> <p>Some of the places I plan to be are the <a href="http://97bottles.com/">97bottles</a> happy hour, the <a href="http://avalonstarevents.com/abx2009/">bowling</a>, <a href="http://upcoming.yahoo.com/event/1407972/" title="South By North West">SXNW</a>, the <a href="http://ellislab.com/sxsw">EllisLab party</a>, the <a href="http://upcoming.yahoo.com/event/1319186/">British Booze-Up</a> and the <a href="http://www.mediatemple.net/go/order/?refdom=29digital.net">MediaTemple</a> closing party, among others. I’ve got <a href="http://happyhour.org/">HappyHour.org</a> and <a href="http://austin.adactio.com/">Adactio Austin</a> safely installed on my phone, and will be having a closer look at <a href="http://www.chinwag.com/blogs/sam-michel/30-handy-resources-sxsw-interactive">this impressive list of resources</a> tomorrow before catching the early train to Heathrow first thing on Thursday morning.</p> <p>We’re staying right on 6th, in an apartment about a block from the convention centre - a significant improvement on my first South-By, when we made the mistake of selecting the Days Inn, over a mile-and-a-half up the interstate. I’m looking forward to some late mornings with such a short walk to get to the panels.</p> <p>See you all there! </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/community.jpg" id="article_image" alt=""> <div id="date">Mar <span>05</span></div> <div id="content"> <h1>Four tips for making more money while staying local</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C15/business">Business</a>, <a href="http://v4.thewatchmakerproject.com/category/C16/freelancing">Freelancing</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>1:18am <i>on</i> Thursday 5th March, 2009</dd> </dl> <p>John Nunemaker of <a href="http://orderedlist.com/">Ordered List</a> recently wrote about <a href="http://orderedlist.com/articles/is-the-web-recession-proof">the effect that the current state of the economy is having on his company</a>, and by extension the web development industry. Like many other colleagues, John and Steve have found that business has actually picked up over the last six months; however, one point that John made got my attention:</p> <blockquote><p>Every piece of work that we are commissioned to do comes from the reputations that Steve and I have built online. Geographically, our closest client to date was almost 100 miles away. Our clients find us online and we work remotely for them, which opens up far more opportunities than if we focused on the local chamber of commerce. Recently, someone asked me what the market was like in South Bend. My response was, “I don’t know.”</p></blockquote> <p>While there are some lucky companies or individuals that have the influence or reputation to work solely online, there are many of us who must rely on local connections and affiliations—and it’s that aspect of freelancing that I want to look at here, with four tips for improving your income while staying local.</p> <h2>1. Make local connections</h2> <p>The number one piece of advice for finding work locally is to make contact with as many other local web designers or developers as possible. They are not the competition, to be either resented (in the case of big, successful agencies) or pitied (omg they still use tables for layout?!); instead see every local web worker as a potential partner, outsourcer or contractor.</p> <p>By creating—or being part of—a local network of tried and trusted suppliers, you will be able to take on more, and more varied, work than when working alone. Finding other designers or developers with complementary skillsets to your own lets you confidently pitch for work outside your comfort zone, safe in the knowledge that your local “Flash guy” or “Joomla guru” is available to take on what you can’t handle. And by making yourself available to other local companies or individuals, especially if you are a specialist in a hard-to-find area, you will quickly find yourself swamped with requests.</p> <p>One of the best ways to get in touch with other web professionals in your area is to join a community group such as <a href="http://www.refreshingcities.org/">Refresh</a>. There are Refresh groups in many major cities across the US and UK, or there will be many other diverse user groups and professional associations meeting regularly in your area. And if there isn’t a group that suits your needs—why not start one yourself?</p> <p>I started <a href="http://www.refreshcambridge.org/">Refresh Cambridge</a> in 2006 when I moved to the city, and since then almost 300 people have joined the mailing list or attended the monthly sessions. And in return for the investment of my time and energy in setting up the group, I have made dozens of strong connections with other Cambridge-based freelancers, which in turn has led to several lucrative projects—work that I would never have landed without those local connections.</p> <p>Participating in a mailing list or speaking at a local event is also a great way to promote yourself as an expert in your field, so grab every opportunity to share your skills or help out other people—you never know what opportunities it might lead to.</p> <h2>2. Find your neighbours online</h2> <p>The second way to make sure you are never far away from what is happening nearby is to join your local community online. By that I mean you should find the online social spaces where your geographical neighbours can be found.</p> <p>I’m a big fan of <a href="http://www.twitter.com/">Twitter</a>, but until recently most of the people I followed and interacted with were not even on the same continent as me, let alone in the same city. That has now changed, and—partly as a result of Refresh and the naturally high geek quotient on Twitter—I am now also following and speaking with many people in my local area, both within and outside of the web industry. Simply by being myself I can effectively advertise my presence and areas of expertise to a local audience.</p> <p>Other opportunities for local online participation might be your town/city forum, local newspaper forums, or other local interest groups with web presences. I’m certainly not suggesting spamming your services all around your corner of the web, but a well-placed forum signature or consistently helpful advice about the web can position you as a local expert and the guy to turn to when anyone needs any design or development work carrying out.</p> <h2>3. Participate in offline community</h2> <p>Another way to make connections within your local community is to get involved with offline community projects or groups. Many business blogs recommend joining your local <a href="http://www.britishchambers.org.uk/">Chamber of Commerce</a> or <a href="http://www.rotary.org/">Rotary Club</a>, but there are often opportunities in other, less business-oriented, arenas. Attend classes at your local community centre or school, or volunteer with community groups or your local church, and you’ll meet many locals outside of your normal social circle, all of whom could be a potential client or referral.</p> <p>I volunteer as a governor at my local school, which—in addition to providing me with the chance to think about something other than web development once in a while—has introduced me to a circle of people, all of whom are active in their community, and all of whom now know their friendly neighbourhood web designer! These kinds of connections are worth far more than an expensive advert in your local newspaper; there’s nothing like word of mouth recommendations for bringing in work.</p> <p>(I should point out that none of these opportunities will work for you if you approach them at all cynically, with an eye for a fast buck—if you’re going to join groups or volunteer your time, do it for the right reasons. The fact that it may also help your business is a bonus, but it shouldn’t be your sole motivation.)</p> <h2>4. Search engine optimisation</h2> <p>Finally, what about some practical advice to finish with? If you want to attract local clients, there are some simple steps you should take to optimise your blog or portfolio site to capture local searches. As with any SEO, think about the sort of searches people might be performing. For me, this might mean:</p> <ul> <li>“cambridge web design”</li> <li>“web designers in cambridge”</li> <li>“cambridgeshire web development”</li> <li>“web design near cambridge”</li> </ul> <p>and various other arrangements of those key search terms. My website should include pages optimised for those various target phrases, but it’s also worth considering your alternative target market: other web designers. Include specific technologies and systems in your optimisation—and often there is much less competition for SERP’s places than for the more popular phrases above—and open yourself up to traffic from industry colleagues looking for help with your favourite platform.</p> <p>I experienced this myself recently, when I was contacted by a local information architect looking for some help with an <a href="http://www.expressionengine.com/">ExpressionEngine</a> project. He had searched online, and apparently I was the <em>only</em> relevant result for “expressionengine cambridge” (albeit via an old page that only mentioned EE in the footer). Needless to say, I will shortly be adding a dedicated ExpressionEngine entry to <a href="http://www.29digital.com/" rel="me">my freelance site</a> to ensure that I don’t miss any similar opportunities.</p> <h2>Summary</h2> <p>While it is true that the internet has broken down borders and removed the need to only deal with clients in your immediate area, there is still a great deal of opportunity to be had right outside your front door. By participating in both the online and offline life of your home town, you will open doors that can lead to rewarding—and profitable—relationships. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/capitals.jpg" id="article_image" alt=""> <div id="date">Feb <span>13</span></div> <div id="content"> <h1>Really Simple JavaScript toTitleCase() Implementation</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C14/javascript">JavaScript</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>5:46pm <i>on</i> Friday 13th February, 2009</dd> </dl> <p>Googling for a quick answer to a problem I was having, I noticed today that there are no really simple solutions listed in the <a href="http://www.google.co.uk/search?hl=en&q=javascript+totitlecase">search results</a> to a JavaScript implementation of <code>toTitleCase()</code> (the natural partner to the existing String methods <code>toLowerCase()</code> and <code>toUpperCase()</code>.</p> <p>So I made this one.</p> <h2>JavaScript TitleCase method</h2> <p>It’s not incredibly clever, but it does what I needed it to, and will probably be sufficient for your needs 90% of the time. The script extends the JavaScript <code>String</code> type with a new <code>toTitleCase()</code> method, which simply converts all the words in the string to their title-cased (i.e. the first letter is capitalised) equivalent. It effectively ignores words that are already upper-cased, and works fine with strings that include numbers.</p> <pre class="code"> String.prototype.toTitleCase = function () { var A = this.split(' '), B = []; for (var i = 0; A[i] !== undefined; i++) { B[B.length] = A[i].substr(0, 1). <span class="linewrap">»</span> toUpperCase() + A[i].substr(1); } return B.join(' '); } </pre> <p>Include the above snippet in your script somewhere, and you can then call the method in the same way as the other String functions:</p> <pre class="code"> var s = "This is a sentence."; var t = s.toTitleCase(); </pre> <p>Neat and simple, and sufficient for most of your JavaScript title-casing needs. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/cachebuster.jpg" id="article_image" alt=""> <div id="date">Feb <span>04</span></div> <div id="content"> <h1>New ExpressionEngine extension: Cachebuster</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>4:06pm <i>on</i> Wednesday 4th February, 2009</dd> </dl> <p>Ever find yourself explaining to a client (for the umpteenth time) how to press F5 so they can see the changes you just made to their site? If you’re being responsible in terms of performance by <a href="http://developer.yahoo.net/blog/archives/2007/05/high_performanc_2.html">setting far-future expiry dates</a> on your site assets, clearing the cache is often necessary to pick up minor tweaks to CSS or JavaScript - but rather than deal with yet another email from a confused client, wondering why their site layout is broken, I thought I’d find a way to automate this step.</p> <h2>Who ya gonna call?</h2> <p><a href="http://github.com/matthewpennell/mgp.ee_cachebuster.ee_addon/">Cachebuster</a> is a new ExpressionEngine extension that allows you to automatically append a variable to your external CSS or JavaScript files. Changing this variable when you update a file tells your visitor’s browser that it is a new file and should be re-downloaded, instead of using a cached version. For a full explanation, see <a href="http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/">Stefan Hayden’s post on CSS Caching from 2006</a>.</p> <h2>Installation</h2> <p>As this extension relies on hacking the core EE files, it is <strong>NOT</strong> recommended for mission-critical sites or applications. However, if you are confident that you can maintain the necessary hack (including when upgrading) you shouldn’t have any problems. (If you forget to upgrade, the extension will fail silently.)</p> <h3>Hacking a new hook</h3> <p>Open the <strong>/system/core/core.output.php</strong> file and locate the following lines (around line 272 in EE1.6.5):</p> <pre class="code"> /** ----------------------------------- /** Fetch the buffered output /** -----------------------------------*/ echo $output; </pre> <p>We are going to add a new hook for our extension to allow us to manipulate the HTML output just prior to sending it to the browser. Add the new lines shown below:</p> <pre class="code"> /** ----------------------------------- /** Fetch the buffered output /** -----------------------------------*/ // MGP Cachebuster 030209: Added new hook to do stuff with // the final browser output if (isset($EXT->extensions['before_display_final_output'])) { $output = $EXT->call_extension('before_display_final_ <span class="linewrap">»</span> output', $output); } echo $output; </pre> <p>We also need to make sure we can refer to the <code>$EXT</code> object - scroll up to the start of the <code>display_final_output()</code> function (around line 94) and add <code>$EXT</code> to the declared globals on the first line of the function:</p> <pre class="code"> global $IN, $PREFS, $TMPL, $BM, $DB, $SESS, $FNS, $LOC, $EXT; </pre> <h3>Installing the extension</h3> <p>Installing the Cachebuster extension is exactly the same as installing any other extension:</p> <ol> <li>Copy the <code>ext.cachebuster.php</code> file into <strong>/system/extensions</strong></li> <li>Copy <code>lang.cachebuster.php</code> into <strong>/system/language/english</strong></li> <li>Visit your Extensions Manager and enable the new extension</li> </ol> <h3>Using the Cachebuster</h3> <p>When you visit the Settings page for the Cachebuster extension, you will see five fields:</p> <ul> <li><strong>Current version</strong> – This is the version number that will be appended to CSS or JS files to force visitors to load the latest version instead of a cached version</li> <li><strong>Apply version numbers to CSS files</strong> – Choose whether you want to control CSS files</li> <li><strong>CSS filenames</strong> – A comma-separated list of stylesheets you want to affect (either with or without the ”.css” extension)</li> <li><strong>Apply version numbers to JavaScript files</strong> – Choose whether you want to control JavaScript files</li> <li><strong>JavaScript filenames</strong> – A comma-separated list of external scripts you want to affect (either with or without the ”.js” extension)</li> </ul> <p>Every time you make a change to a CSS or JavaScript file and upload it to the live website, you can now login to the Cachebuster extension settings and increment the version counter. Any files flagged for inclusion will have that number appended to their filename:</p> <pre class="code"> <link rel="stylesheet" type="text/css" href="/css/layout.css <span class="linewrap">»</span> ?v=42"> </pre> <h2>Feedback and bug reports</h2> <p>There are a few obvious drawbacks to this version 1.0 of the extension. The most obvious one is the need for a hack to the core EE files - hopefully EE2.0 will introduce new hooks we can use without the need to hack.</p> <p>The extension also appends the version number to <em>every</em> file (or at least those listed in the settings); this means that even if you have only edited one file, incrementing the version number will force visitors to download every file as if it were new. Of course, for true speed tweaks you should be concatenating your stylesheets and script files, so you should only have one or two external files at most.</p> <p>If you have any suggestions for how to improve Cachebuster, please either comment below or on the <a href="http://wiki.github.com/matthewpennell/mgp.ee_cachebuster.ee_addon">GitHub Wiki for Cachebuster</a>.</p> <div class="github"> <h3><a href="http://github.com/matthewpennell/mgp.ee_cachebuster.ee_addon/">Visit GitHub to download files</a></h3> </div> <p><strong>What is GitHub?</strong> GitHub is a web application that uses the version control software Git to allow its members to manage their code online. I am hosting the files for this article there so that any bugfixes or improvements I make can be found in one central location. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/rearwindow.jpg" id="article_image" alt=""> <div id="date">Jan <span>31</span></div> <div id="content"> <h1>Show, don’t tell - Hitchcock’s Rear Window masterclass</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C13/film">Film</a>, <a href="http://v4.thewatchmakerproject.com/category/C12/writing">Writing</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>11:47pm <i>on</i> Saturday 31st January, 2009</dd> </dl> <p>If you’ve ever opened up a book on screenwriting, one of the cardinal rules drummed into writers is: “Show, don’t tell.” Film is a visual medium — if you want to convey some information, it is far better to communicate that information visually than have a character spell out what you want the audience to know. (A truism exploited by Mike Myers in the <a href="http://www.imdb.com/find?s=all&q=austin+powers">Austin Powers films</a>, where all story exposition is delivered — with a straight face — by a character aptly named Basil Exposition.)</p> <p>Phyllis is afraid of dogs? Then write a scene where she has to deal with an overly friendly mutt — but definitely <em>don’t</em> have her mention to someone else: “Hey, you know what? I’m really frightened of dogs.” It sounds forced; unnecessary verbiage that could have been avoided through better writing.</p> <h2>Forty seconds of perfect cinema</h2> <p>Hitchcock was a master of visual storytelling, and there is no better example of this “show don’t tell” philosophy than the introductory shot of James Stewart in the classic <a href="http://www.imdb.com/title/tt0047396/">Rear Window</a>.</p> <div class="video"><p> </p><object width="450" height="338" data="http://vimeo.com/moogaloop.swf?clip_id=3026688&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1"> <param name="allowfullscreen" value="true"> <param name="allowscriptaccess" value="always"> <param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=3026688&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1"> <embed src="http://vimeo.com/moogaloop.swf?clip_id=3026688&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed> <a href="http://vimeo.com/3026688">Rear Window opening scene - Show, Don’t Tell</a> from <a href="http://vimeo.com/user590173">Matthew Pennell</a> on <a href="http://vimeo.com">Vimeo</a> </object> </div> <p>With not a word of dialogue or voiceover, the audience has been told:</p> <ul> <li>Our hero’s name</li> <li>The most important aspect of his character (at least with respect to the plot) — a broken leg has confined him to a wheelchair</li> <li>How he sustained that injury, capturing a shot of a dramatic motor-racing crash</li> <li>Which tells us the type of man he is: a risk-taker</li> <li>What he does for a living, and how good he is at it — would an enthusiastic amateur have their photo on the cover of a Paris fashion magazine?</li> </ul> <p>Communicating all that information verbally, and in a way that didn’t seem forced or unnatural (<q>“Why, good morning Mr Jefferies — it won’t be long before you’ve recovered from that terrible accident at the racetrack where you broke your leg; you’ll be back to work as a famous risk-taking photographer in no time!”</q>), would have required several conversations with conveniently ignorant minor characters. Hitchcock manages it in forty seconds and one camera move.</p> <p>Genius.</p> <h3>If you’re interested in more Hitchock</h3> <p>I highly recommend the <a href="http://www.amazon.co.uk/Hitchcock-14-Disc-Box-Set/dp/B000BND224/thewatchmaker-21">Hitchcock Box Set</a>, which has fourteen of his greatest films — Vertigo, The Birds, Marnie, Frenzy, Topaz, The Trouble With Harry, Torn Curtain, Psycho, Family Plot, Saboteur, Shadow Of A Doubt, The Man Who Knew Too Much and Rope, in addition to Rear Window — and is available for an incredible sub-£20 on Amazon or in the shops. All the DVDs come with great extras, too.</p> <p>Or, if you want to improve your writing, I also recommend the <a href="http://onthepage.tv/podcast.php">On The Page podcast</a>, hosted by script consultant Pilar Alessandra. Each week Pilar and guests discuss various aspects of the “craft and business of screenwriting” and answer listeners’ questions. Despite the occasional <abbr title="Los Angeles">LA</abbr>-specific suggestions, it’s always an entertaining 45 minutes of discussion and advice. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/widget.jpg" id="article_image" alt=""> <div id="date">Jan <span>26</span></div> <div id="content"> <h1>SXSW Countdown - a dashboard widget for OS X</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C11/macintosh">Macintosh</a>, <a href="http://v4.thewatchmakerproject.com/category/C10/sxsw">SXSW</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>10:26pm <i>on</i> Monday 26th January, 2009</dd> </dl> <p>If you’re heading to Austin, Texas in March for geek spring break (otherwise known as the <a href="http://www.sxsw.com/interactive/">South By South West interactive</a> festival) you’re probably counting down the days already. What? You’d love to have something to help scratch that itch? Well, say no more - I have just the thing!</p> <h2>And it only took twenty minutes</h2> <p>Creating an OS X dashboard widget is simplicity itself. First, find <a href="http://www.mactricksandtips.com/2008/03/how-to-make-your-own-dashboard-widgets.html">some helpful instructions</a> written by someone who know what they are doing. Next, open Dashcode and find that one of the pre-existing widgets is a countdown widget, meaning all you have to do is re-arrange the canvas elements and make some new graphics. Photoshop. Export. Rinse and repeat until satisfied with the result.</p> <h3>How to install your SXSW widget</h3> <p>If you’re not using Mac OS X, why are you still reading? There’s nothing for you here.</p> <p>Mac users - download the archive below, unzip it, and double-click the <code>SXSWCountdown.wdgt</code> file to install it on your Dashboard. Position it front-and-centre, and check back regularly to watch the days tick down!</p> <div class="download"> <h3><a href="/downloads/SXSWCountdown.zip">Download ZIP (152KB)</a></h3> </div> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/books.jpg" id="article_image" alt=""> <div id="date">Jan <span>17</span></div> <div id="content"> <h1>Reading List 2008</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C9/books">Books</a>, <a href="http://v4.thewatchmakerproject.com/category/C3/Personal">Personal</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>10:14pm <i>on</i> Saturday 17th January, 2009</dd> </dl> <p>This time last year (and with a little help from <a href="http://www.allconsuming.net/" title="Track your book consumption, among other things, online">All Consuming</a>) I looked back at the books I had read over the past twelve months. 2007’s haul was <a href="http://v3.thewatchmakerproject.com/journal/445/reading-list-2007">an impressive forty-four books</a>; in 2008, however, I overdosed on door-stop fantasy novels bringing the total down to a less respectable twenty-six.</p> <h2>No Stalgia</h2> <p>Unlike last year, I did not re-visit <em>any</em> old favourites this time. I also read very few non-fiction books (at least compared to last time around). Here’s the full list.</p> <h3>Fiction</h3> <p>I’m still trying to fill the gaping classic literature-shaped holes in my reading record. The year started off well, with some Kingsley Amis and Mary Shelley, but then somehow took a left-turn into modern lit before becoming bogged down in turgid epic fantasy.</p> <ul> <li>The Transit of Venus (Shirley Hazzard)</li> <li>Lucky Jim (Kingsley Amis)</li> <li>Last Exit to Brooklyn (Hubert Selby, Jr)</li> <li>Frankenstein (Mary Shelley)</li> <li>American Gods (Neil Gaiman)</li> <li>No Country For Old Men (Cormac McCarthy)</li> <li>Last Argument of Kings (Joe Abercrombie)</li> <li>Dead Air (Iain Banks)</li> <li>Atonement (Ian McEwan)</li> <li>Starship Troopers (Robert A Heinlein)</li> <li>Maskerade (Terry Pratchett)</li> <li>Little Brother (Cory Doctorow)</li> </ul> <h4>Comic books</h4> <p>Not very many graphic novels this year, but <em>Watchmen</em> is definitely on my reading list this year before the film comes out in March.</p> <ul> <li>1602 (Neil Gaiman)</li> <li>The Complete WildC. A. T.s (Alan Moore)</li> </ul> <h4>Enormo-fantasy novels by George RR Martin</h4> <p>I’m a huge fan of quasi-historical fantasy author Guy Gavriel Kay, and discussions of the “you might also like” variety on <a href="http://www.brightweavings.com/forums/home.htm">the official GGK forums</a> almost always turned up George RR Martin as a recommendation, so I finally took the plunge and dived into his epic “A Song Of Ice And Fire” series. And very good it is too.</p> <ul> <li>A Game of Thrones</li> <li>A Clash of Kings</li> <li>A Storm Of Swords Part 1: Steel And Snow</li> <li>A Storm Of Swords Part 2: Blood And Gold</li> <li>A Feast for Crows</li> </ul> <h3>Non-fiction & autobiography</h3> <p>A bit of web design, a little screenwriting, some drug-fuelled debauchery, every bit of science known to man, and the saviour of the 21st century…</p> <ul> <li>Building Findable Websites: Web Standards SEO and Beyond (Aarron Walter)</li> <li>Blink: The Power of Thinking Without Thinking (Malcolm Gladwell)</li> <li>Save The Cat! The Last Book on Screenwriting You’ll Ever Need (Blake Snyder)</li> <li>Web Form Design: Filling in the Blanks (Luke Wroblewski)</li> <li>The Principles of Beautiful Web Design (Jason Beaird)</li> <li>Slash (Slash)</li> <li>A Short History of Nearly Everything (Bill Bryson)</li> <li>Dreams From My Father (Barack Obama)</li> </ul> <h2>Top Picks</h2> <p>Without a doubt the best book I read last year was Bill Bryson’s <a href="http://www.amazon.co.uk/Short-History-Nearly-Everything/dp/0552997048/thewatchmaker-21">A Short History of Nearly Everything</a>, an exploration of just about every branch of science for the benefit of the uneducated everyman. It’s that rarest of things - an approachable science book; it does for science what <a href="http://www.amazon.co.uk/Sophies-World-Novel-History-Philosophy/dp/1857992911/thewatchmaker-21">Sophie’s World</a> did for philosophy.</p> <p>Aside from <em>Short History</em>, I also rated <a href="http://www.amazon.co.uk/Last-Exit-Brooklyn-Hubert-Selby/dp/0714531294/thewatchmaker-21">Last Exit To Brooklyn</a> (by Hubert Selby Jr, the author behind <em>Requiem For A Dream</em>); and Barack Obama’s first book, <a href="http://www.amazon.co.uk/Dreams-My-Father-Story-Inheritance/dp/1847673511/thewatchmaker-21">Dreams From My Father</a>, was also a good read - I hadn’t realised that it was written so long ago, when Obama was around my age in fact.</p> <p>For 2009 I’ll be tracking my reading as per usual, although I have a feeling I’ll be using the excellent <a href="http://www.readernaut.com/">Readernaut</a> this time around. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/html.jpg" id="article_image" alt=""> <div id="date">Jan <span>06</span></div> <div id="content"> <h1>Fun and games and audio and video with HTML5</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C8/html">HTML</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>6:35pm <i>on</i> Tuesday 6th January, 2009</dd> </dl> <p>If you’re the sort of person that enjoys poking around in other people’s code, you’ll have already noticed that this site is built with <span class="caps">HTML5</span>, the latest and greatest and very much still in-progress flavour of <span class="caps">HTML</span>. As <a href="http://adactio.com/journal/1540">Jeremy noted the other day</a>, that decision has placed me in pretty lofty company this week, with <a href="http://uxlondon.com/">UX London</a> and <a href="http://aneventapart.com/">An Event Apart</a> both launching in the last few days and boasting the same stripped down doctype.</p> <h2>Choosing HTML5 was an easy decision</h2> <p>There have been a fair few articles written on the impending ascendancy of <span class="caps">HTML5</span> as the de-facto standard for the web over the next few years. Back when I was curating Digital Web, we published an article comparing <a href="http://www.digital-web.com/articles/html5_xhtml2_and_the_future_of_the_web/"><span class="caps">XHTML2</span> and <span class="caps">HTML5</span></a> - the author, David Andersson, confidently declared that “<span class="caps">HTML5</span> will be the future of the web”, and given the evidence it was difficult to disagree with him. A List Apart also published a <a href="http://www.alistapart.com/articles/previewofhtml5">preview of <span class="caps">HTML5</span></a>, and in September last year Ian Hickson gave <a href="http://ajaxian.com/archives/html5-demos">a fantastic demo of <span class="caps">HTML5</span> features</a> at Google.</p> <p>So, there seemed little reason not to make the move to <span class="caps">HTML5</span>, not least because as far as I could tell one could do so by simply starting to use a much easier-to-remember doctype - everything else was icing, and I could introduce actual <span class="caps">HTML5</span> features as and when they were supported by browsers. My <a href="http://www.29digital.com/">freelance portfolio</a> also uses <span class="caps">HTML5</span>, but is otherwise indistinguishable from <span class="caps">HTML5</span> - but for this site, I decided to kick the tyres on some of the new elements that are available.</p> <h2>Poetry ... makes familiar <object>s be as if they were not familiar.</h2> <p>Two of the new <span class="caps">HTML5</span> elements discussed in the <span class="caps" title="A List Apart">ALA</span> article were the <code><audio></code> and <code><video></code> tags.</p> <p>Until now, if you wanted to place audio or video in a web page, you had to use a combination of the <code><embed></code> tag (for Firefox) and the <code><object></code> tag (for Internet Explorer), together with some gobbledygook attributes to make sure the browser knew what you were trying to achieve.</p> <p><span class="caps">HTML5</span>, on the other hand, defines two straightforward, easy to comprehend tags, and I was drawn to the fact that one could place markup inside them which would be rendered <em>if the browser did not recognise the new element</em>. They have built-in graceful degradation! Here is the markup for the “standout tracks” on my recent <a href="http://www.thewatchmakerproject.com/blog/top-10-albums-of-2008/">top 10 albums</a> post:</p> <pre class="code"> <div class="audio"> <h3>Standout track: Troublemaker</h3> <audio src="/audio/Troublemaker.mp3" controls> <object type="application/x-shockwave-flash" <span class="linewrap">»</span> data="/audio/player.swf" id="audioplayer3" <span class="linewrap">»</span> height="24" width="290"> <param name="movie" value="/audio/Troublemaker.mp3"> <param name="FlashVars" value="playerID=3& <span class="linewrap">»</span> soundFile=/audio/Troublemaker.mp3"> <param name="quality" value="high"> <param name="menu" value="false"> <param name="wmode" value="transparent"> <a href="/audio/Troublemaker.mp3">Download song (MP3)</a> </object> </audio> </div> </pre> <p>By placing a valid <code><object></code> Flash player inside the <code><audio></code> tag, and a simple link to download the <span class="caps">MP3</span> file inside <em>that</em>, the track will still be available to visitors using browsers that don’t support the new element, <em>and</em> browsers that don’t have Flash installed. And it’s all perfectly valid <span class="caps">HTML5</span>!</p> <p>(I’m using the <a href="http://www.1pixelout.net/code/audio-player-wordpress-plugin/">1 Pixel Out Audio Player Wordpress plugin</a> and the instructions for non-WP blogs by <a href="http://www.macloo.com/examples/audio_player/">Mindy McAdams</a> - I chose this one because I liked the way it looked and worked on the <a href="http://therissingtonpodcast.co.uk/" title="Tally ho!">Rissington Podcast</a>.)</p> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/audio_players.gif" alt="Audio player controls in Safari and Firefox" width="372" height="108" class="five col" title="Audio player controls in Safari and Firefox"></p> <p>The end result will differ <a href="http://wiki.whatwg.org/wiki/Implementations_in_Web_browsers">depending on your browser of choice</a>. Opera and Safari 3.1 will use their native audio players, while Firefox, <span class="caps">IE</span>, and most other browsers will display the Flash player interface. Non-Flash browsers will display a simple <span class="caps">HTML</span> link to download the <span class="caps">MP3</span> file.</p> <h3>This may or may not be the wrong way to embed video</h3> <p>As well as music clips, I wanted to embed YouTube clips that I had bookmarked via my <a href="http://www.tumblr.com/" title="Tumblr, a micro-blogging service that powers my footer links">Tumblr</a> feed. The <span class="caps">HTML5</span> <code><video></code> element is as simple to use as <code><audio></code>, albeit with a few extra optional attributes. However, I ran into one major problem - YouTube links are not in a supported video format; they are SWF files (in actual fact wrappers for other SWF files), so even in supported browsers the <code><video></code> elements wouldn’t work.</p> <p>I had a choice to make. Either I could place the object/embed combo directly in the page, or I could wrap it in a <code><video></code> element anyway in the name of forward-planning, and use JavaScript to replace the unsupported video with a regular Flash player. Initially I chose the latter path, but on further consideration I have now ditched the <code><video></code> element. Perhaps in the future they will support SWF (I don’t pretend to understand all the conversations about codecs and such) and they will make a return, but for now it seemed illogical to use an element whose only purpose was to be immediately overwritten.</p> <h2>When all browsers support all formats, markup will be so much easier</h2> <p>Until that time, I believe my <code><audio></code> setup offers the best combination of technologies; native where possible, enhanced Flash player if available, and plain <span class="caps">HTML</span> downloads for all. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/albums.jpg" id="article_image" alt=""> <div id="date">Jan <span>04</span></div> <div id="content"> <h1>Top 10 albums of 2008</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C4/music">Music</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>4:27am <i>on</i> Sunday 4th January, 2009</dd> </dl> <p>As a part-time musician and full-time music lover, I’ve written precious little about music. And sometimes, when I notice that I’ve spent the entire day listening to albums that were released within six months of each other in mid-1991, I wonder if somehow I’ve lost touch with what makes discovering new music so exciting. Have I crossed an invisible line in my mid-thirties; is all I can expect from the future an inevitable downward spiral into dad-rock and easy listening?</p> <p>So this year I have made a conscious effort to seek out new music. Last.fm throws up some reasonable recommendations from time-to-time, but word-of-mouth tips – from Twitter, mailing lists, or private forums – are generally more reliable and a great deal more eclectic. Peer-to-peer is a boon in this respect; I’ve got into the habit of downloading material as it is recommended by those whose taste I know matches my own, which has led to some great finds over the last twelve months. And as the year draws to an end, “Best Of” lists have also provided pointers to albums I would not have otherwise acquired.</p> <p>All of which is by way of introduction to this – my top ten albums of 2008, <a href="http://www.last.fm/user/Watchmaker/charts?rangetype=6month&subtype=albums">as judged by the impartial Audioscrobbler over the last six months</a>. (Why six months and not twelve? So as not to give too unfair an advantage to albums released earlier in the year, of course – and also to better align the final results with how my mental scoreboard figures the year.)</p> <h2>10. Viva La Vida (Coldplay) / Dear Science (TV On The Radio)</h2> <p>Tying for last place, both of these albums have featured heavily in end of year polls. <a href="http://www.amazon.co.uk/Viva-Vida-Death-All-Friends/dp/B00180OSXG/thewatchmaker-21">Viva La Vida (Or Death And All His Friends)</a> (to give it it’s full title) was <a href="http://www.last.fm/bestof/2008/album/1;">#1 on Last.fm for 2008</a> despite not being as immediately catchy as 2005’s <a href="http://www.amazon.co.uk/X-Y-Coldplay/dp/B0006L16N8/thewatchmaker-21">X&Y</a>, of which I was a big fan, it definitely improves with each listen, and is a more mature and adventurous album than anything Coldplay have done to date.</p> <p>TV On The Radio were a complete unknown when I came across their album on a Pownce-powered favourites list, but since first hearing <a href="http://www.amazon.co.uk/Dear-Science-TV-Radio/dp/B001DXPTOU/thewatchmaker-21">Dear Science</a> it’s been picked as album of the year by several notable publications, including Rolling Stone, <span class="caps">MTV</span>, and Spin Magazine. Think a synth-powered Interpol jamming with Scissor Sisters.</p> <h2>9. Brain Thrust Mastery (We Are Scientists)</h2> <p>New York trio (now duo) We Are Scientists’ first album, the awesomely catchy <a href="http://www.amazon.co.uk/Love-Squalor-We-Are-Scientists/dp/B000BCHJ2E/thewatchmaker-21">With Love And Squalor</a>, would probably feature in my all-time top five, so I picked up their sophomore effort, <a href="http://www.amazon.co.uk/Brain-Thrust-Mastery-Are-Scientists/dp/B0012NHN72/thewatchmaker-21">Brain Thrust Mastery</a>, as soon as it came out in March. It’s less riff-driven and more ambitious than their debut, but still guaranteed to have you dancing round the living room, straining to hit the pitch-perfect vocal harmonies. I was gutted to find out that they were playing here in Cambridge on the very day I was to fly out to Texas – definitely high on my list of bands to see live.</p> <h2>8. The Seldom Seen Kid (Elbow)</h2> <p>Despite almost unanimous thumbs-up recommendations from friends, I’d never paid any attention to Elbow (with the exception of <a href="http://www.rathergood.com/independent_woman">their cover of Independent Woman, accompanied by Joel Veitch’s animated kittens</a>), but when <a href="http://www.amazon.co.uk/Seldom-Seen-Kid-Elbow/dp/B0013F2M52/thewatchmaker-21">The Seldom Seen Kid</a> won the <a href="http://www.nationwidemercurys.com/">Mercury Music Prize</a>, I caved in and picked up a copy. I think it needs a few more listens to really grow on me – it’s one of those albums that demands concentration.</p> <h2>7. Glasvegas (Glasvegas)</h2> <p>I don’t remember where I first heard of <a href="http://www.amazon.co.uk/Glasvegas/dp/B00198HE4C/thewatchmaker-21">Glasvegas</a> – I think possibly they were featured on an early morning T4 special – but I was instantly struck by the singer’s broad Weegie accent giving their indie rock something of a “Proclaimers do Coldplay” feel.</p> <h2>6. Fleet Foxes (Fleet Foxes)</h2> <p>Another album with a good showing in the end of year charts was the debut self-titled album by Seattle folk band <a href="http://www.amazon.co.uk/Fleet-Foxes/dp/B00180OTAI/thewatchmaker-21">Fleet Foxes</a>. Given a few more months’ listening, this would certainly be higher than #6; it’s difficult to categorise, but if you like your modern folk heavy on the vocal harmonies and light on instrumentation it’s definitely one to check out.</p> <h2>5. Death Magnetic (Metallica)</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/deathmagnetic.jpg" alt="Death Magnetic album cover" width="216" height="216" class="col three"></p> <p class="no-indent">Into the top five now, and first up is a triumphant return to form for an old favourite. I’d not bought a Metallica album since 1991’s <a href="http://www.amazon.co.uk/Metallica/dp/B00000B9AM/thewatchmaker-21">black album</a>, but the generally positive comments <a href="http://www.amazon.co.uk/Death-Magnetic-Metallica/dp/B001FTTY48/thewatchmaker-21">Death Magnetic</a> was attracting on music forums prompted me to give it a go – and I’m very glad I did.</p> <p>As long ago as 2006, Lars Ulrich said that the band was working on new material reminiscent of “old school” Metallica, and the ghosts of classic early albums such as “Master of Puppets” and “…And Justice For All” can be heard in the high-speed thrash of tracks like “All Nightmare Long” and “That Was Just Your Life”. Unfortunately James Hetfield’s lyrics still have a tendency towards sixth-form angst – “Love is a four letter word!” he bellows on first single and weakest track, <a href="http://www.youtube.com/watch?v=jZ5zXXUJsyc">The Day That Never Comes</a> – but despite the occasional clumsy wordplay, you can’t help but be swept along by the monstrous riffs and memorable lyrical hooks.</p> <div class="audio"> <h3>Standout track: Broken, Beat & Scarred</h3> <audio src="/audio/BrokenBeatScarred.mp3" controls> <object type="application/x-shockwave-flash" data="/audio/player.swf" id="audioplayer1" height="24" width="290"> <param name="movie" value="/audio/BrokenBeatScarred.mp3"> <param name="FlashVars" value="playerID=1&soundFile=/audio/BrokenBeatScarred.mp3"> <param name="quality" value="high"> <param name="menu" value="false"> <param name="wmode" value="transparent"> <a href="/audio/BrokenBeatScarred.mp3">Download song (MP3)</a> </object> </audio> </div> <h2>4. American Demo (The Indelicates)</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/americandemo.jpg" alt="American Demo album cover" width="216" height="216" class="col three"></p> <p class="no-indent">For some reason I had it in my mind that I had picked up The Indelicates debut album, <a href="http://www.amazon.co.uk/American-Demo-Indelicates/dp/B001495LLY/thewatchmaker-21">American Demo</a>, after a Mercury Music Prize nomination, but on checking I find that that wasn’t actually the case. So call it fate, call it luck, karma, whatever – but I’ve been listening to their perfect indie-pop ever since. Of course, the relatively high showing for this one might have something to do with my daughters’ obsession with the track <a href="http://www.youtube.com/watch?v=HcM9QsZNRxM">Sixteen</a>, which made it <a href="http://www.last.fm/user/Watchmaker/charts?rangetype=6month&subtype=tracks">my most listened track by quite a long way</a> this year, thanks to multiple plays every time I drove them anywhere.</p> <div class="audio"> <h3>Standout track: Sixteen</h3> <audio src="/audio/Sixteen.mp3" controls> <object type="application/x-shockwave-flash" data="/audio/player.swf" id="audioplayer2" height="24" width="290"> <param name="movie" value="/audio/Sixteen.mp3"> <param name="FlashVars" value="playerID=2&soundFile=/audio/Sixteen.mp3"> <param name="quality" value="high"> <param name="menu" value="false"> <param name="wmode" value="transparent"> <a href="/audio/Sixteen.mp3">Download song (MP3)</a> </object> </audio> </div> <h2>3. The Red Album (Weezer)</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/redalbum.jpg" alt="Weezer red album cover" width="216" height="216" class="col three"></p> <p class="no-indent">Aside from <a href="http://www.youtube.com/watch?v=FiIC5qcXeNU">Buddy Holly</a> with its great video, I’d not heard anything by Weezer until a friend bought <a href="http://www.amazon.co.uk/Weezer-Red-Album/dp/B0019M632C/thewatchmaker-21">their latest untitled-but-red album</a>. I ripped it, assuming it might get a couple of listens – and then played the hell out of it for the rest of the year.</p> <p>It’s likely that part of the affection I have for the album stems from The Greatest Video Of All Time™, the meme-laden <a href="http://www.youtube.com/watch?v=WanLLnVixC4">Pork and Beans</a>, but it’s full of great tracks. Singer and main songwriter Rivers Cuomo stated that he tried to move away from traditional song arrangements and try new approaches, as well as sharing songwriting duties with other band members; for me, it’s worked a little too well – despite loving this album, I’ve not developed an appreciation of their back catalogue.</p> <div class="audio"> <h3>Standout track: Troublemaker</h3> <audio src="/audio/Troublemaker.mp3" controls> <object type="application/x-shockwave-flash" data="/audio/player.swf" id="audioplayer3" height="24" width="290"> <param name="movie" value="/audio/Troublemaker.mp3"> <param name="FlashVars" value="playerID=3&soundFile=/audio/Troublemaker.mp3"> <param name="quality" value="high"> <param name="menu" value="false"> <param name="wmode" value="transparent"> <a href="/audio/Troublemaker.mp3">Download song (MP3)</a> </object> </audio> </div> <h2>2. The ’59 Sound (The Gaslight Anthem)</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/the59sound.jpg" alt="The '59 Sound album cover" width="216" height="216" class="col three"></p> <p class="no-indent">Now this choice I do know where it came from. A <a href="http://twitter.com/dkr/status/969926052">tweet from D Keith Robinson</a> led me to The Gaslight Anthem’s second album, and their perfect mix of punk and Springsteen New Jersey attitude. I’ve since sought out their debut, <a href="http://www.amazon.co.uk/Sink-Swim-Gaslight-Anthem/dp/B000QUUDLU/thewatchmaker-21">Sink or Swim</a> – a much rawer record, significantly closer to punk than Paramus – but it’s not as immediate as <a href="http://www.amazon.co.uk/59-Sound-Gaslight-Anthem/dp/B0017V7GTY/thewatchmaker-21">The ’59 Sound</a>, which takes Springsteen-like tales of small-town dreams and wraps them in an up-tempo soundtrack that manages to sound both modern and classic at once.</p> <p>I also love the borrowed lyrics, whether as blatant as the line from Counting Crows’ “Round Here” that kicks off the chorus to “High Lonesome”, or the other, more subtle, references that crop up in other tracks.</p> <div class="audio"> <h3>Standout track: High Lonesome</h3> <audio src="/audio/HighLonesome.mp3" controls> <object type="application/x-shockwave-flash" data="/audio/player.swf" id="audioplayer4" height="24" width="290"> <param name="movie" value="/audio/HighLonesome.mp3"> <param name="FlashVars" value="playerID=4&soundFile=/audio/HighLonesome.mp3"> <param name="quality" value="high"> <param name="menu" value="false"> <param name="wmode" value="transparent"> <a href="/audio/HighLonesome.mp3">Download song (MP3)</a> </object> </audio> </div> <h2>1. Chinese Democracy (Guns N’ Roses)</h2> <p><img src="http://v4.thewatchmakerproject.com/images/uploads/chinesedemocracy.jpg" alt="Chinese Democracy album cover" width="372" height="372" class="col five"></p> <p class="no-indent">And so to my number one album of 2008, the long-awaited (and boy is that an understatement!) <a href="http://www.amazon.co.uk/Chinese-Democracy-Guns-N-Roses/dp/B001JEO9XU/thewatchmaker-21">Chinese Democracy</a> by Guns N’ Roses. Was it worth waiting seventeen years for? No, not by any stretch of the imagination. Is it <em>really</em> Guns N’ Roses? Well, not really; to all intents and purposes it’s The Axl Rose Show, supported by a revolving door of supporting musicians. But really there’s only one question that matters: Is it any good? Hell, yes!</p> <p>Somewhat predictably, after waiting fifteen years for a new Guns album (seventeen since their last original material, 1991’s Use Your Illusion I & II), I was a little underwhelmed on first hearing Chinese Democracy; is this really what Axl has spent a third of his life, and over $13m, to create? iTunes was mostly two and three stars – it was passable rock music, but nothing special. But then circumstances conspired to make me re-assess the album.</p> <p>In late November, our middle daughter was taken into hospital with pneumonia, from where she was swiftly transferred to a specialist heart and lung hospital for surgery. Two hours from home, my wife and I spent a fretful couple of weeks shuttling back and forth, alternating between dealing with our other two girls and sitting impotently in a hospital ward. Those journeys, driving alone in a dark December along the M1 and A14, gave me plenty of opportunity to listen to my new, unimpressive album… and something strange started to happen.</p> <p>Without the looming shadow of Guns’ past successes, the new material started to impress on its own merit. Axl’s voice has not lost any of its strength (as one might have expected after so long out of the limelight); his range and power is still awe-inspiring, from the patented alley-cat scream that introduces the title track, through the growling vocals on techno-tinged singalong “Shackler’s Revenge”, to the purity of funk-pop faux-Bond anthem, “If The World”.</p> <p>But does it sound like a Guns N’ Roses record? Surprisingly, it does; whether that is testament to Axl’s songwriting and arranging contributions (on both this and previous releases), or the ability of new contributors like Paul Tobias and Dizzy Reed to mould their songwriting to an existing blueprint, I really couldn’t say, but the album definitely slots neatly into the existing back catalogue. Stylistically, it’s heavy on non-traditional song structures – many of the tracks lack a clearly defined chorus, but still manage to stand up as coherent and cohesive numbers. Initially the lack of Slash felt like a glaring omission, but that feeling also passed with time; despite the confusing array of guitarists involved (up to five on a single song) the solos eventually came to feel like they belonged too.</p> <p>“Chinese Democracy” is not just a great rock album, able to hold its own against most great records of the last ten years; it’s a great Guns N’ Roses album. </p> <div class="audio"> <h3>Standout track: Prostitute</h3> <audio src="/audio/Prostitute.mp3" controls> <object type="application/x-shockwave-flash" data="/audio/player.swf" id="audioplayer5" height="24" width="290"> <param name="movie" value="/audio/Prostitute.mp3"> <param name="FlashVars" value="playerID=5&soundFile=/audio/Prostitute.mp3"> <param name="quality" value="high"> <param name="menu" value="false"> <param name="wmode" value="transparent"> <a href="/audio/Prostitute.mp3">Download song (MP3)</a> </object> </audio> </div> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/scroll_to_comment.jpg" id="article_image" alt=""> <div id="date">Jan <span>03</span></div> <div id="content"> <h1>New ExpressionEngine extension: Scroll to new comment</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C5/expressionengine">ExpressionEngine</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>4:44am <i>on</i> Saturday 3rd January, 2009</dd> </dl> <p>While developing this incarnation of The Watchmaker Project I came across one glaring omission in my new CMS of choice, the awesome ExpressionEngine.</p> <p>Sure, the guys at EllisLab like to tell us how flexible their application is - how it can run multiple sites, online shops, enormous government portals - but for something that started off as a blog engine, why doesn’t it offer the ability to return to the comment you just added? It was frustrating, so I dug into the core code to see what could be done. Luckily there was a hook in just the right place for a shiny new extension. And here it is.</p> <div class="update"><strong>Update 27/01:</strong> At the prompting of Nathan Pitman of <a href="http://ninefour.co.uk/">NineFour</a>, I’m moving this and all future code posted here onto the free source control host, <a href="http://github.com/">GitHub</a>. It makes sense - this way I can make updates to posted code without having to update blog posts.</div> <h2>Scroll To Comment</h2> <p>Like all ExpressionEngine extensions, the steps to get this up and running are pretty simple:</p> <ol> <li>Download and unzip the files from the package</li></li> <li>Place the <code>ext.scroll_to_comment.php</code> extension file in the <code>/system/extensions</code> folder of your EE install</li> <li>Place the <code>lang.scroll_to_comment.php</code> language pack in the <code>/system/languages/english</code> folder</li> <li>Visit your EE Control Panel, and navigate to <strong>Admin > Utilities > Extensions Manager</strong></li> <li>Enable the new extension</li> <li>Visit the ‘Settings’ page to change the prefix setting if necessary</li> <li>You’re good to go!</li> </ol> <h3>A few quick words on CSS id attributes</h3> <p>As noted <a href="http://veerle.duoh.com/blog/comments/implementation_of_my_comments_in_expression_engine/">a while back by Veerle</a>, if you want your code to be 100% W3C valid you can’t start a CSS <code>id</code> attribute with a number. That is why this extension provides the option of including a prefix to all comment ids, which you will have to match up with your (X)HTML markup - here’s mine:</p> <pre class="code"> {exp:comment:entries sort="asc"} <li id="c_{comment_id}"> <h4><strong>{url_as_author}</strong> at <span class="linewrap">»</span> {comment_date format="%g:%i%a"} on {comment_date <span class="linewrap">»</span> format="%j%S %F, %Y"} <a href="#c_{comment_id}"> <span class="linewrap">»</span> #</a></h4> <blockquote> {comment} </blockquote> </li> {/exp:comment:entries} </pre> <p>All the comments on my site are prefixed with “c_” - and, as long as I also use that in my extension settings, every time anyone submits a comment the page will reload displaying their new comment.</p> <div class="github"> <h3><a href="http://github.com/matthewpennell/mgp.ee_scroll_to_comment.ee_addon">Visit GitHub to download files</a></h3> </div> <p><strong>What is GitHub?</strong> GitHub is a web application that uses the version control software Git to allow its members to manage their code online. I am hosting the files for this article there so that any bugfixes or improvements I make can be found in one central location. </p> </div> <img src="http://v4.thewatchmakerproject.com/images/uploads/wireframe.jpg" id="article_image" alt=""> <div id="date">Jan <span>02</span></div> <div id="content"> <h1>Redesign 2009</h1> <dl id="meta"> <dt>Categories:</dt> <dd><a href="http://v4.thewatchmakerproject.com/category/C6/design">Design</a>, <a href="http://v4.thewatchmakerproject.com/category/C7/the-site">The Site</a></dd> <dt>Tags:</dt> <dd></dd> <dt>Published:</dt> <dd>1:45am <i>on</i> Friday 2nd January, 2009</dd> </dl> <p>Looking back through my archives, the last time this site was redesigned was back in November 2005. That fairly successful design served me well for the last three years, but since the beginning of 2008 I’ve been itching to redesign. And, finally, I’ve managed to see a new design through to actual launch.</p> <h2>Goodbye Textpattern; Hello ExpressionEngine</h2> <p>The biggest change is in the application that powers the site. Textpattern was a reliable and free blog engine, but I’ve long desired to join the ExpressionEngine jet-set, and the last month of building this site has convinced me that it is a great choice for any project that needs a CMS of any description (possibly with the exception of an online shop - the e-commerce module is not exactly fully-featured, although I’m sure they are working on improvements with the impending release of version 2.0).</p> <p>Speaking of EE 2.0, I’m now looking forward to the rewritten, CodeIgniter-powered ExpressionEngine even more than before. The opportunity to use my existing experience and knowledge of the CI framework to build and extend sites powered by EE opens up a whole new avenue of freelance work to PHP coders like me.</p> <h2>Small pieces, loosely joined</h2> <p>This particular design is relatively new, having begun life as a notebook sketch in mid-November. The idea to bring together the various streams of data I’m generating - Twitter, Flickr, All Consuming, Last.fm - is much older, but by no means original; there are several ‘lifestream’ applications around now, but I’d much rather present an aggregated view of my online activity on my own domain, rather than a third-party site such as Chi.mp.</p> <p>The external services are imported via cURL scripts that run periodically to retrieve XML data via their respective APIs. Each script either inserts data directly into the ExpressionEngine weblog tables, or writes to flat HTML files for inclusion in my templates. At least, that was the idea; unfortunately I’m having some issues with PHP versions at the moment, so an interim solution will have to be swiftly coded tomorrow.</p> <h2>Evolution</h2> <p>I always like to see how other designers work, so in case anyone feels the same way and is interested in seeing how the design evolved, here is a short animation of the stages through which the homepage went, from wireframe to final version:</p> <p class="no-indent" style="margin-top: 1.5em;"><img src="http://v4.thewatchmakerproject.com/images/uploads/twp_animated_mock.gif" alt="animated design progression" width="450" height="769"></p> </div> </div> <!-- /inner --> </div> <!-- /article --> <div id="comment-form"> <div class="inner"> <div id="offset"> <p class="intro">I'd love to hear what you think - please use the form below to leave your comments. Anything I consider too offensive, off-topic, or spammy will be deleted at my discretion. Some HTML is permitted, or you can use <a href="#">Textile</a>.</p> </div> <div id="comments"> <ol> </ol> </div> </div> </div> <!-- /comment-form --> <div id="footer"> <div class="inner"> <div id="tumblr"> <h2>Related Entries</h2> <ol> </ol> </div> <div id="copyright"> © All content is copyright 2008-14 Matthew Pennell. All rights reserved. Comments remain the property of their respective authors. </div> <!-- /copyright --> <div id="right"> <div id="feeds"> <h2>Subscribe <i>to</i> RSS</h2> <p>If you use RSS, you can subscribe to receive updates when new content is added to the site. Choose from the following options:</p> <ul> <li><a href="/rss/blog">Blog entries only</a></li> <li><a href="/rss/links">Links, videos, and quotes only</a></li> <li><a href="/rss/full">All content in one feed</a></li> </ul> </div> <!-- /feeds --> <div id="search"> <h2>Search <i>the</i> site</h2> <form method="post" action="http://v4.thewatchmakerproject.com/" > <div class='hiddenFields'> <input type="hidden" name="ACT" value="19" /> <input type="hidden" name="XID" value="c78098c635854d881f4b5d59149f59431d5286e3" /> <input type="hidden" name="RP" value="search_results" /> <input type="hidden" name="NRP" value="search_results" /> <input type="hidden" name="RES" value="" /> <input type="hidden" name="status" value="" /> <input type="hidden" name="weblog" value="journal" /> <input type="hidden" name="search_in" value="entries" /> <input type="hidden" name="where" value="all" /> <input type="hidden" name="site_id" value="1" /> </div> <div> <input type="text" name="keywords" maxlength="100" size="20"> <button type="submit">Search</button> </div> </form> </div> <div id="credits"> <h2>Validation <span class="amp">&</span> Credits</h2> <p>This site is <a href="http://validator.w3.org/check?uri=http://v4.thewatchmakerproject.com/blog/show-do&charset=(detect+automatically)&doctype=Inline&group=0">valid HTML5</a>, and mostly <a href="http://jigsaw.w3.org/css-validator/validator?uri=http://www.thewatchmakerproject.com/c/twp.css&profile=css3&usermedium=all&warning=1&lang=en">valid CSS2/3</a> with the odd browser-specific extension where necessary.</p> <p>The large icons on the home page are by <a href="http://www.crystalxp.net/galerie/en.id.3751-bagg-a-png.htm">Bagg & Box</a>, <a href="http://www.vistaicons.com/icon/i148s0/old_school_icons.htm">VistaIcons</a> and <a href="http://perishablepress.com/press/2006/08/20/a-nice-collection-of-feed-icons/">Perishable Press</a>. Any smaller icons are of course by <a href="http://www.famfamfam.com/">FamFamFam</a>. Stock photography mostly from <a href="http://www.sxc.hu/">stock.xchng</a>.</p> <p>Blog powered by <a href="http://www.expressionengine.com/index.php?affiliate=thewatchmakerproject">ExpressionEngine</a>. Links powered by <a href="http://www.tumblr.com/">Tumblr</a>.</p> <p>Hosted by <a href="http://www.mediatemple.net/">(mt) MediaTemple</a>.</p> </div> <!-- /credits --> </div> <!-- /right --> </div> </div> <!-- /footer --> <script> window.onload = function () { // Fix heights of blocks in footer var left_col = document.getElementById('tumblr').offsetHeight; if (document.getElementById('video')) { var middle_col = document.getElementById('video').offsetHeight + document.getElementById('quotes').offsetHeight + document.getElementById('copyright').offsetHeight; } else { var middle_col = document.getElementById('right').offsetHeight; } if (document.getElementById('video')) { if (left_col > middle_col) { document.getElementById('copyright').style.height = (left_col - (document.getElementById('video').offsetHeight + document.getElementById('quotes').offsetHeight)) + "px"; } } else { document.getElementById('footer').style.height = document.getElementById('footer').childNodes[1].style.height = (left_col > middle_col) ? left_col + "px" : middle_col + "px"; } window_onload(); } </script> <script src="/js/blog.js"></script> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-71160-5']); _gaq.push(['_setDomainName', 'thewatchmakerproject.com']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> </body> <!-- page rendered in 0.8878 seconds --> </html>