Wednesday, May 27, 2009

Ubuntu 9.04 and NVIDIA Driver

I have been using Ubuntu for quite a while and I loved it for it's simplicity. I downloaded and installed 9.04 in my machine last night and to my surprise I no longer get the nice pop-up prompting me to install proprietary NVIDIA driver for my NVIDIA 8800 GTS graphics card.

The "nv" driver worked fine but it doesn't allow me to enable desktop effects. Also, I really want the full hardware acceleration so I can do some OpenGL programming. After search around the ubuntu package repository, I found several versions of the old familiar nvidia-glx. So I installed the latest one with:
sudo apt-get install nvidia-glx-180
Another surprise was that it no longer updates the xorg.conf file for me so I ended up running nvidia-xconfig myself by:
sudo nvidia-xconfig
This overrides the xorg.conf file to make sure X server loads the proprietary "nvidia" rather than open source "nv" driver. I wonder what the Ubuntu team was thinking, this definitely felt like a step backward. Were they trying to push people to use the open source "nv" driver?

Tuesday, May 26, 2009

East Coast Trip

I met a former colleague who was born in Hawkes bay and had some random chat about work and holidays. This was when I realised that even though I’ve been living in New Zealand for 12 years, I’ve never travel to the east coast of north island before. Therefore, when my wife said she felt like to go for a holiday I immediately suggested that we should travel to the east.

Day 1

Napier is quite far away from Auckland (420 km, ~6 hours drive according to Google Map), so we’ve decided to stop by few other cities alone the way. Our first stop was Rotorua, which is famous for its geothermal sites and hot pools. After checked into our hotel, we were wondering around the street trying to find a place for dinner. Eventually, I pulled out my iPhone, browsed to tripadviser.com, found a highly rated bar Pig & Whistle and found it using iPhone GPS and Google Map. I just can’t imagine how to live without iPhone and Internet these days. After dinner, we visited the Polynesian Spa, which is quite famous in New Zealand for its geothermal hot pools.

Day 2

Our plan for the day was to drive from Rotorua to Napier. We stopped by Huka fall prawn farm and Lake Taupo along the way. We arrived Huka fall prawn farm at around 11am and joined the hatchery tour to see how they feed prawns. All I can say is life of a prawn is sad, you either fight and eat your fellow prawns or be eaten. We actually saw that in action, a prawn killed another one and ate it.

After the tour we went on to prawn fishing, we spent one hour sitting in the cold winter and just couldn’t catch any. We gave up at the end because we were so cold and hungry. We had lunch in the prawn farm restaurant then headed to Taupo. We didn’t spent too much time in Taupo, we took a short walk around the lake side, the museum and the city centre then headed off to Napier.

The first half of the drive was quite enjoyable, it was flat and road was straight with nice country side views. We stopped by a nice little lookout alone the way. The second half, however, were terrible. It was all mountain road and unbelievably foggy. Eventually, We managed to arrived Napier safely and checked into the hotel at around 5:30pm

Day 3

The third day was quite a boring one. Firstly, the weather was crap, it was wet and cold. Secondly, I somehow had this horrible stomach ache and I can’t walk a long distance or eat anything. We visited few lookout in the morning but then I slept through the afternoon.

Day 4

My stomach finally recovered after a whole day rest and we decided to join the guided Art Deco walking tour in Napier. There was a massive 7.8 earthquake in Napier in early 30s, which destroyed most of its commercial district. They rebuild the whole city with the most modern architecture style of that period called  Art Deco.  I really enjoyed the tour and the guide told very nice stories about the city and its buildings. I would definitely recommend anyone who have a chance to visit Napier to join the guided tour.

We had lunch at Cobb & Co in Napier, which had really nice 2 course lunch for just $10, visited the mission estate winery and then we were on our way to Gisborne.

Day 5

According to Wikipedia, Gisborne is the first city to see the sun shine each day. Therefore we decided to wake up early in the morning to see the sunrise. We waked up at 6am and I was kinda worried that the sun will already be up by the time we reach the beach. Our sacrifice to sleep did pay off, the sky was clear and the sunrise was really beautiful.

After seeing the sunrise, we drove to the Tolaga Bay, it has the longest concrete wharf in New Zealand. At 660m, it is said to be the longest concrete wharf in the southern hemisphere. That was pretty much the last stop of our east cost trip. We were heading back home.

We headed off to Tauranga after lunch and it took us around 4 hours to reach there. We took a walk in Mt Mauao and had dinner in a Turkish restaurant.

Day 6

It was time to go home, I had been computer-less for 5 days and I really missed it. We stopped by the Karangahake Gorge, which has a 1 meter long dark tunnel. We tried to walk through it but it was just way too dark and scary. We only spent around 5 minutes in it then headed back to our car.

We arrived Auckland at around 5pm and gosh the weather was miserable.

Saturday, May 16, 2009

Referencing Local Variables in jQuery Callback Functions

One day I was working on a CRUD application, which contains a lot of form fields and controls. Each of them requires a mouse over event handler to display a tooltip message. After lots of copy’n’pasting, I decided to refactor the repetitive event registration code out and put them into a loop.

To test out my idea, I developed a very simple page with just three <div>s:

<div id="div1">Click me</div>
<div id="div2">Click me</div>
<div id="div3">Click me</div>

and a list of messages indexed by the <div>s’ ID:

var messages = new Object();
messages['div0'] = 'hello'; 
messages['div1'] = 'bonjour'; 
messages['div2'] = 'ciao';

When someone click on one of the <div>’s region, I would like to show a popup an dialog and display the message associated with it’s ID. Since my goal was to eliminate repetitive lines of code, I put the event registration code in a loop:

for(var i=0; i<3; ++i) {
  $("#div" + i).click(function() { 
    alert(messages['div' + i]); 
  });
}

When I tried this out, instead of showing the right message, the alert box always shows ‘undefined’:

image

After a lot of head scratching, I finally realised that the problem is with this line of code referencing the loop variable i:

alert(messages['div' + i]);

The computer scientists’ way of describing this is that it formed a “Closure” referencing the variable i. Since this line of code sits inside the callback function,  the ‘div’ + i statement wasn’t evaluated to ‘div0’, ‘div1’ and ‘div2’ in each loop iteration as I expected. Instead, because each of the callback function holds a reference to the variable i, the ‘div’ + i statement was using the final value of i, which is 3 in this case.

This can be proven by changing the alert statement to show the value of i, which will always be 3 when any of the <div>s is clicked.

alert(i);

I Googled around for solutions but most of them are pretty complicated but eventually I found an answer in the jQuery reference document. All jQuery objects have a data() method, which allows you to bind any data to it. The bound data will be instance specific and the value will be evaluated at the binding time.

Therefore, to fix my code I just have to change the event registration code to:

for(var i=0; i<3; ++i) {
  $('#div' + i).data('divID', 'div' + i);
  $('#div' + i).click(function() {
    alert(messages[$(this).data('divID')]); 
  });
}

So in each iteration of the loop, the value ‘div0’, ‘div1’ and ‘div2’ are stored into the ‘divID’ data section of the respective <div> objects and then the callback function uses the stored value to find out which message to display when they are clicked.

The final solution looks like this:

$(function() {
  var messages = new Object();
  messages['div0'] = 'hello'; 
  messages['div1'] = 'bonjour'; 
  messages['div2'] = 'ciao';
         
  for(var i=0; i<3; ++i) {
    $('#div' + i).data('divID', 'div' + i);
    $('#div' + i).click(function() { 
      alert(messages[$(this).data('divID')]); 
    });
  }      
});