Tuesday 30 June 2009

The Importance of 'this' Scope Management Through Javascript Event Handlers

During the development of vBulletin 3.x, much of our Javascript code started to take on a far more object-oriented style. With more widespread use of client-side scripting for features that would appear multiple times on a page, such as popup-menus vBMenu and collapsible elements vBCollapse, having encapsulated code made development much easier.

With one exception - event handling.

Let's take some very simple code to illustrate the problem. The purpose of this code is to force all links to be diverted through a different script. It's overkill, but it illustrates the problem.
function linkRedirect(link_element)
{
this.redirect_base = "http://example.com/redirect?url=";
this.link_element = link_element;
this.link_element.addEventListener("click",
this.handleClick, false);
}

linkRedirect.prototype.handleClick = function(e)
{
e.preventDefault();

// The following will not work
window.location = this.redirect_base
+ escape(this.link_element.getAttribute("href"));
}
In order to get around this, one can use a closure and refer to it instead of this in the event handler callback, like this:

function linkRedirect(link_element)
{
this.redirect_base = "http://example.com/redirect?url=";
this.link_element = link_element;

var closure = this;
this.link_element.addEventListener("click", function(e)
{
e.preventDefault();
closure.execRedirect();
}
, false);
}

linkRedirect.prototype.execRedirect = function()
{
window.location = this.redirect_base
+ escape(this.link_element.getAttribute("href"));
}
Unfortunately, closures can be a great source of memory leaks, especially in Internet Explorer, and are best avoided if possible.

Mid-way through the development of vBulletin, we came across the Yahoo! User Interface (YUI) library, which wraps all this stuff into one beautiful function, which allows this to be passed as a parameter to the callback:
function linkRedirect(link_element)
{
this.redirect_base = "http://localhost/~kier/jq/redirect.php?url=";
this.link_element = link_element;

YAHOO.util.Event.on(this.link_element, "click",
this.execRedirect, this, true);

}

linkRedirect.prototype.execRedirect = function(e)
{
e.preventDefault();
window.location = this.redirect_base
+ escape(this.link_element.getAttribute("href"));
}
Isn't that fantastic?

So why am I writing about this? Well, I've been playing with jQuery and found to my horror that it does not have this scope management system by default, requiring a revertion to the bad old days of closures and helper functions... ugh.

Today, I'm going to attempt to extend jQuery to be able to pass scope parameters in the same way that YUI does. Good luck me...

Sunday 28 June 2009

Garlic and Ginger Chicken Fried Rice

This is a recipe I've been making for a long time now. It's not traditional chinese in any way shape or form, nor does it claim to be. It's just easy to cook and delicious, take it or leave it.

Since Jo was diagnosed coeliac, I've had to make a few changes to the recipe, such as making hers with gluten-free ingredients, but essentially it's remained the same since I started cooking it many years ago, with minor tweaks here and there.

Firstly, let's have a list of ingredients.
  • Thai fragrant jasmine rice (or american long grain if you can't get jasmine - just not easy cook rice - that stuff is rancid!)
  • Fresh eggs
  • Chicken (or turkey) breasts
  • Frozen peas
  • Fresh root ginger
  • Fresh garlic
  • Light soy sauce (I like to use golden label superior soy, but light soy is fine)
  • Worcestershire sauce (Lea and Perrins)
  • Chinese five-spice powder
  • Chinese shaohsing rice wine (or dry sherry)
  • Pure sesame oil
  • Cornflour / corn starch
  • Salt
  • Monosodium glutamate (MSG, yeah I know I know, but the amount I use isn't going to make bits drop off you or anything...)
Begin by measuring out as much rice as you want to cook. I usually do a cup or two per person, as I tend to eat this as a meal in its own right.

Next, you need to wash the rice thoroughly. I start with a few cups in a sieve running water through it, then I transfer the rice to a pan and let water fill the pan and overflow for several minutes, until the water is no longer cloudy.

When that is done, cook the rice in the normal manner. Best results always come from a dedicated rice cooker. Err on the side of very slightly underdone rice rather than allowing it to become mushy - mushy rice does not fry well at all.

After the rice is cooked, allow it to cool for as long as possible. The longer you can leave it the better - the frying works best with cold rice. If the rice is still hot when you fry it, it will tend to steam in the wok rather than fry, which gives a different flavour.

While the rice is cooling, you can prepare the rest of the ingredients.

Mix around a tablespoon of rice wine with a good glug of soy sauce, a teaspoon of five-spice and half a teaspoon of cornflour.

Slice up the meat and place it into the mix, stirring it so all the meat is coated. Leave it for a few minutes to soak up some of the flavours.

Next, heat up a wok. For this dish, extreme heat is all important, so although those of you with 'non-stick' woks will be able to have a go at this, they never get hot enough. What you really need is the sort of wok you can pick up for about £10 ($16) from a chinese supermarket. They are made of very thin steel, start off silver in colour and are only non-stick if you use them properly!

Turn the heat to full and when the wok starts to smoke, pour in about a tablespoon of oil. I use groundnut oil, but vegetable or sunflower oil is fine. When the oil is just starting to smoke, drop in the meat and stir fry vigorously until cooked.


Remove the meat from the wok, allow it to drain for a few minutes, then slice it again into matchstick-sized strips.

Next, roughly chop the garlic and ginger together, then stick it into a processor to mince it.

Don't blitz it too hard, you still want little pieces rather than a paste.

Now it's time for the rice, so wipe down the wok to remove whatever may be left behind from cooking the meat.

Break open an egg and beat it until the yolk and white are all together, as if you were making an omelette. When this is done, heat up another tablespoon of oil in the wok and wait until it's just started to smoke. All of this is done on maximum heat.

This next part is very rapid and time-critical, so be prepared. Pour the egg into the wok and quickly move it around so as to break it up. Before the egg has cooked through (there should still be some uncooked, liquid egg in the wok) drop a spoonful or two of rice onto the egg, then quickly toss and turn the wok's contents so the rice and egg are well mixed. Add a good pinch of salt, a tiny bit of MSG and half a teaspoon of the ginger and garlic mixture. Stir fry vigorously. Do not over-fill the wok with rice, or too much heat will be lost and the food will not cook in the proper manner.

When the rice starts to take a little colour from the frying, add a spoonful of peas, some of the meat and about ten drops of worcestershire sauce.

Continue to fry the rice, keeping it moving to prevent it burning on the bottom of the wok.

After a few minutes the rice will be a little darker, though you must choose this point yourself depending upon your taste. Add a splash of soy sauce (maybe a teaspoonful?) and mix it into the rice for a few seconds, then empty the rice into a waiting container.

You will need to repeat these steps multiple times in order to fry all your rice, because you will almost certainly have prepared more rice than will fit into a single frying stint.

When all the rice is fried and set aside, drizzle a few drops of pure sesame oil into the rice and mix it in. This stuff has a very potent flavour, so be sparing!



Allow the rice a few minutes to cool, then dig in!

Om nom nom nom.

Saturday 20 June 2009

The Leap of Faith

A person told me not so long ago that I was standing on the ledge of a metaphorical window, and that I was under the impression that it was very high up. That person told me that in fact, the window was not high at all, and that I should step back off the ledge and I would find the ground a safe distance below me.

That person was wrong.

The ground was even further below than I had initially thought. The fall was long and terrifying, and when I finally saw the ground it was far from where I wanted to be.

Tuesday 16 June 2009

vBulletin Style Blogs at vBulletin.com

I have now posted part two of my series of blogs detailing some of the highlights of the vBulletin 4 style system.

Part one dealt with markup and included some screenshots:
First Look: The vBulletin 4.0 Style

Part two, posted today, lays out some of the ways that administrators can make use of new features of the style system in vBulletin 4.0:
vBulletin 4 - Style Variables

Monday 15 June 2009

Rainy Days

I've had this account registered for a while now, saving it for a rainy day.

Check back from time to time, especially if the forecast is for storms.