Hello there. I am Terry and I am a full-time undergraduate based in Singapore. I take photos, write a blog and design websites.

And no, I'm not a teddy bear.

Bookmarked: Nicholas Hance McElroy Photography

Nicholas Hance McElroy Photography

Nicholas Hance McElroy (aka Nick Hance) is a photographer living in the American West. You can find his works on Flickr, as well as on his site.

I adore his work because they have a very subtle vintage look to them. The landscapes are stunning, the portraits are beautiful and inanimate objects are breathing life through his photos.

Money is the root of all evil… thoughts

So it turns out that I might not be going for an exchange program next January afterall.

It took me awhile to acknowledge the fact, but I felt that it is terribly unfair for me to unload the entire financial burden onto my parent’s shoulder when studying in my university (NTU) during that period is just as good as going to Sweden instead.

Sweden is good, sans the whole Julian Assange rape smearing case which Sterling succinctly pointed out to me on Twitter earlier today. The weather there is nice. The people there are very hospitable, welcoming and eco-friendly. Their meatballs are awesome. If all these don’t cut it, at least I know that it is where my favourite furniture chain IKEA was conceived. Okay, but I still hated IKEA for using Verdana.

I just returned from a one-day trip to and from Singapore to attend this talk about the exchange program and how we should navigate ourselves around those miles and miles of crazy bureaucracy red tape. I’m not going to moan, whine, whimper, cry baby about this wasted trip – I did get lots of information about the lovely country from a senior who had just returned from the very country I’ve been yearning to travel, live and study in, and learning more about the exchange program isn’t exactly something half bad.

The gist of the problem lies with the money. I don’t live in a upper-middle class, or a high class family. We don’t rake in money by the five or more figures monthly. My dad works as a project manager cum architect in a small medium enterprise, while my mom spends most of her days cooping in the tuition class handling kids that are so wild I thought nobody could ever get hold of them. Well, at least my mom did.

The entire exchange program will set me back by around S$10,000 to S$12,000, which is a lot. Probably a few times of our household income. My brother still has one more year to see before he finishes college, and God knows what he’ll do after that. S$10,000 might not sound a lot to you (it converts to around US$7,350), but it does mean a lot to a small family like mine.

Because of my academic achievements, I’ve been studying in Singapore, a country 400km south of my hometown, for the past 8.5 (and counting) years, relying solely on scholarships. The first 6 years I was on a government scholarship since graduating from elementary school, and for the next 2.5 I’m on a university-sponsored scholarship that pays for the rest of my tuition fees.

For a very tiny instant moment I felt that all these should count in my advantage because I’ve been saving tons of money for my parents – instead of channeling that money into funding my education, they have stashed them in all forms of investments, bank accounts (probably not a good idea), fixed deposits and anything that has to do with money without actually spending them.

Immediately my conscience came riding on this moral high horse and giving me a mental lecture about how dare I conjunture such a thought – saving my parents that much money doesn’t mean I’m entitled to spend them right now, even if that S$10,000 is going to be just a fraction of it. Who do I think I am, for being so selfish, to think that I should make my parents pay for my exchange program that is so incredibly expensive?

An instant sense of shame overcame myself. I couldn’t possibly think what my parents have been through after I told them that I have set my eyes on Sweden for the exchange programs. Their jaws were left somewhat agape when I broke the news about the overall costs, and I hate myself even the more now for allowing such a lapse of judgement to take place.

So I make sure that I got it clear today – I told them that they shouldn’t care about what I would think. Even if I would feel disappointed and probably be all sad panda when I couldn’t go to Sweden, I know that the lump sum of money could be better spent elsewhere. I’ll give them the choice to choose – and I very well know that it doesn’t lie with me.

I’ll still be matching my courses for the exchange program, but that doesn’t meant that I’m getting my hopes high for parental approval. I’m not bitter about this, and in fact I feel a little embarrassed that I have been engaged in this endless soliloquy with myself throughout the entire day.

Wise up, Terry.

p/s: For once, I’m ecstatic about me being so honest with myself.

Better Form Usability with jQuery

The <label> tag is a rather commonly omitted element in HTML forms. Although the tag does not render text in it differently from those outside the tag, it provides a usability improvement for mouse users by duplicating common GUI features. More importantly, it couples an input element with a label for users of speech browsers.

The <label> tag can be used as is, but it has an extremely useful attribute – the for attribute. This attribute allows one to associate a form control with the element, when its value matches the ID of the form control. Here’s a sample of a usable, but not the best, form, without the use of the <label> tag:

<form id="form-1">
	<p>
		<span>Name</span>
		<input type="text" name="author" tabindex="1" />
	</p>
	<p>
		<span>Email</span>
		<input type="text" name="email" tabindex="2" />
	</p>
	<p>
		<span>URL</span>
		<input type="text" name="url" tabindex="3" />
	</p>
	<p>
		<span>Comment</span>
		<textarea name="comment" tabindex="4" />
	</p>
	<p>
		<input type="submit" name="submit" tabindex="5" value="Submit" />
	</p>
</form>

When we add the the for attribute to the <label> element and assign it a value that is identical to the id attribute of the form control, we will improve the usability of the form. For visually-impaired users, the speech browsers are able to draw a link between a form control and it’s label, which will provide important information and even instructions in filling up the form. For those using visual browsers are, in turn, able to focus on a specific form control when its associated label is clicked on.

Here is the improved form:

<form id="form-1">
	<p>
		<label for="author">Name</label>
		<input type="text" name="author" tabindex="1" id="author" />
	</p>
	<p>
		<label for="email">Email</label>
		<input type="text" name="email" tabindex="2" id="email" />
	</p>
	<p>
		<label for="url">URL</label>
		<input type="text" name="url" tabindex="3" id="url" />
	</p>
	<p>
		<label for="comment">Comment</label>
		<textarea name="comment" tabindex="4" id="comment" />
	</p>
	<p>
		<input type="submit" name="submit" tabindex="5" value="Submit" />
	</p>
</form>

What does jQuery have to do with this?

You must be puzzled – afterall, what you need to do so far is to manually inject the for and id attributes into the <label> and <input> elements respectively. In fact, I was actually doing these manual changes to my theme files and other web-based projects because it will only take me at most a few minutes’ worth of time.

However, I recently faced a problem that I felt using jQuery as a workaround wasn’t a bad idea afterall. Many people would advice against using JavaScript in cases like this for two reasons: some users, albeit a minority, don’t allow JavaScript to run on their browser; and on a related note, with the possibility that JavaScript being disabled in mind, we shouldn’t use it to implement essential features.

The problem was that I was working with some WP plugins that generates HTML forms dynamically and on the fly. Although some would dive into the realm of PHP and make the necessary changes such that the generated forms are more user-friendly, I would prefer using the jQuery way, which is easier and does not require muddling with the source code of the plugin files.

There are a few steps that we have to do:

  1. Retrieve the value of the name attribute of the <input> element.
  2. Assign a unique ID to the <input> element.
  3. Assign the same value (the unique ID) to the for attribute of <label>.

For those copy-happy folks, here’s the code:

jQuery(function ($) {
 	$("#form-1 > p").each(function(count) {
		var input_id = $(this).children("input").attr("name") + (count + 1);
		$(this).children("input").attr("id", input_id);
		$(this).children("label").attr("for", input_id);
	});
});

Dissecting the code

$("#form-1 > p").each(function(count) {

This line searches the document for the paragraphy element, <p> that is a direct descendant of an element with an ID of #form-1. The .each() function makes sure that we look the subsequent function across all elements that satisfy the selection criteria. The count variable is declared and it will be used in each iteration.

var input_id = $(this).children("input").attr("name") + (count + 1);

This line defines the variable input_id, and assigns it the value of that is the that of the name attribute of the <input> element combined with a unique number. The number is increased by a value of 1 after each iteration of the loop so that we will generate unique IDs, even in face of an unprobably scenario that two input fields on the same page share the same value of the name attribute.

$(this).children("input").attr("id", input_id);
$(this).children("label").attr("for", input_id);

These two lines do the same thing – the finds the <input> and <label> elements in the same parent element, and assigns the generated value to the id of the former and for attribute of the latter.

Note

Note that this technique only works if each <label> and <input> pair is located in the same parent element, and each parent element has only one pair of label and input field in it. Of course, there is a solution for those forms that do not wrap each pair in a parent element, but I will not dwell into it.

Inception and Gotham

Gotham, a typeface used in the film, Inception

Gotham, a typeface used in the film, Inception

I have watched Inception last weekend and I have to say it’s a really mind-blowing film. People are saying that Chris Nolan invaded everyone’s dream and planted the idea that the film is great *laughs* but that’s not the main point.

What really caught my attention was the choice of typeface used. It is immediately obvious that they did not use Trajan for their movie posters, something I applaud. Trajan is an overused typeface – and here’s a non-exhaustive list of popular films in the past that have used Trajan in their posters (in fact, there are 153 and counting posters):

  • The Final Destination (2009)
  • One Missed Call (2008)
  • Sex and the City (2008)
  • Bridge to Terabithia (2007)
  • I Am Legend (2007)
  • Star Dust (2007)
  • Final Destination 3 (2006)
  • Requiem (2006)
  • The Core (2003)
  • A Beautiful Mind (2001)
  • The Mummy Returns (2001)
  • The Perfect Storm (2000)
  • The Mummy (1999)
  • City of Angels (1998)
  • Deep Rising (1998)
  • Titanic (1997)
Gotham Typeface

Gotham Typeface

They chose Gotham instead. It is a geometric typeface designed by Tobias Frere-Jones and Jesse Ragan. Familiar typeface, isn’t it? That’s because Gotham has appeared in:

  • Obama’s presidential campaign posters
  • Movie posters of Moon (by the way I recommend you watch this film)
  • Branding for Discovery Channel, USA Network, Astro and more.
  • Chicago’s 2016 Summer Olympics bid.

Launching two new sites

After the past few weeks, I was busy with the work I’m getting from my internship position with a local design firm, but I still managed to dedicate enough free time to two sites I was launching. They’re not really community-powered sites, so there’s nothing hyper about it *laughs*

Tweet Archive (link)

Tweet Archive

Tweet Archive

In light of the recent instability of Twitter, especially over the one-month span of the World Cup, I have decided that backing up my tweets on a remote server will be a wise choice. Not only does the remote server helps to archive all the tweets that I have been posting since then, it also creates a searchable tweet archive. Don’t you find it frustrating that even you yourself can’t comb through your own tweets on Twitter web interface?

However, I was only able to retrieve down to the last 3,200 tweets (dating back to August 2009). The 3,200 cap was placed on Twitter API to prevent it from being overloaded with requests… which means I’ve lost around 5000+ of my older tweets, but it’s okay.

I got the idea after Jeff (@perishable) wrote about backing up his tweets during Twitter’s wobbly period. And he has got his tweets backed up already, too.

Jeff's tweet about archiving his tweets

Jeff's tweet about archiving his tweets

What I did wasn’t exactly quite rocket science (maybe except for the regex part):

  1. Upgrade my site to WP3.0, and activate the WP multisite feature. If you’re done with this step, everything will be a lot easier. Note: Please check with your host if they support wildcard DNS, i.e. *.domain.tld. If such a feature is not offered, it’s not all kaboom. Simply create a new WP installation in the subdomain’s root directory.
  2. Install a new child blog pointing to http://tweets.teddy-o-ted.com
  3. Download your Twitter archive – I recommend TweetBackup. Export the latest 3,200 tweets (or less) as an RSS feed and download it. Try to refrain from tweeting between downloading your Twitter archive and the completion of the set up – you wouldn’t want any tweets to fall through.
  4. Import your Twitter archive to your WP installation. If your server is slow, the import script might exceed the 30-second execution time limit and you will encounter a timeout error. Don’t panic. Go to your WP installation and check the earliest tweet that was successfully imported. Return to your RSS file, and remove all entries prior to that, which should shave a sizeable chunk of bytes off the original RSS file. Reimport the file.
  5. Install Alex King’s TwitterTools WP plugin. The plugin has quite a lot of function, but I configured it such that it only imports my tweets and post them. The plugin can also create a tweet from your WP post, but enabling this feature might cause a non-ending loop (although it is claimed that the plugin is designed to avoid such fireball of death, you should be smart enough to avoid it).
  6. Get a theme. Doug has an excellent one, go get it. Alternatively, you can modify any WP themes you want. The theme I am using for my tweet archive is a modification of Sandbox, modeled after Doug’s theme as well.
  7. Regex. If you’re quick, you’ll notice that all imported tweets lack outbound links for @replies and #hashtags. I wrote a short php function to do this. Insert the following lines into your theme’s functions.php file:
    // Makes URLs, @usernames and #hastags in tweets clickable
    function tweet_replies_url_filter($content) {
    	// Prevent premature texturizing
    	remove_filter('the_content', 'wptexturize');
     
    	// Replaces username with clickable link
    	$pattern_username = '/\@(\w+)/';
    	$replace_username = '@<a href="http://twitter.com/'.strtolower('\1').'">\1</a>';
    	$content = preg_replace($pattern_username,$replace_username,$content);
     
    	// Replaces hashtag with clickable link
    	$pattern_hashtag = '/\#([a-z][A-Z])(\w+)/';
    	$replace_hashtag = '#<a title="Search Twitter for \2" href="http://search.twitter.com/search?q=\2">\2</a>';
    	$content = preg_replace($pattern_hashtag,$replace_hashtag,$content);
     
    	/* Uses internal WP command make_clickable to replace URLs with clickable link */
    	$content = make_clickable($content);
    	add_filter('the_content', 'wptexturize');
    	return $content;
    }
    add_filter('the_content', 'tweet_replies_url_filter');

For more information, you can read it up here. Doug has done a great writeup on establishing your own Tweet Archive.

tdy.co (link)

tdy.co - A personal URL shortener

tdy.co - A personal URL shortener

When the .co domain was opened to the general public on the 21st of July, I wasn’t very sure what domain name do I want. The first thing that actually went through my mind was to purchase tmun.co because tmun.com was already parked (and I have no idea why). When searching for available domain names on GoDaddy I decided to try my luck and started jamming the searchform with 3 letter acronyms of my site, my nickname or my other pseudonyms.

Try.co, taken. Tsd.co, taken. Ted.co, taken. Tdy.co, still available. What?!

I jumped. Immediately I billed $26 to my credit card and snagged the domain name before anyone else does. I had no idea what I wanted to do with it until I saw Dean’s tweet about converting his new domain, djr.co, into a personal URL shortener and I thought, hell, why not?

I downloaded a fork of Shaun Inman’s Lessn, developed by Alan Hoogan, called Lessnmore. Lessn is a great simple tool and is a lot lighter than Yourls, but it doesn’t support custom slugs unless I modify the database entry. I dug around and arrived at Lessnmore. It’s an extension of Lessn, and has a little more functionality with the same API hooks as Lessn.

tdy.co/1 points to this site :)

The tdy.co main page is a little plain. However, it is a significant example because it is my first HTML5 page. I’ve never really got into using HTML5 in my current projects because of my unfamiliarity with it, so I’m more than elated that it worked out just fine on tdy.co.

Page 1 of 19112345102030...Last »

Hello Easter Egg hunter! You've discovered the magic of the Konami Code!

Yea. You probably know what the Konami code is before getting to this page. So now what? Here is a randomised YouTube video on my favourites list... which includes Rickroll, if you're luck enough to get it.

You are currently watching The Hula Song. Loving it? You can even watch the video in its full screen glory :)

The Konami Code:
Konami Code sequence