12 April, 2006

0 is false !

When using || or && to test between several expressions which is the first to be true and taken as the whole value, be carefull with numbers! I had a bas experience this morning using a decremential counter.

I was doing some code 10 times and then reinitializing the counter for the next use of the function. In the context of a DIV Element, my code was the following:

//Function to make DIV blink
this.blink = function() {
//Blink 10 times
this.times = (this.times-1)||10;
//If not 10 times yet
if ( this.times > 0 ) {
//Switch blink color
if ( this.times%2==0 )
this.style.backgroundColor = '#000';
else
this.style.backgroundColor = '#FFF';
this_ = this;
//Redo blink in 50 milliseconds
setTimeout('this_.blink()', 50);
else { //Times out, stop blinking, reset counter value
clearTimeout();
this.times = 10;
}
}

My point is on the very first line of the function:
this.times = (this.times-1)||10;
What it does is affecting 10 when this.times doesn't exist yet and then affects 9, 8, 7,...
But when it comes to 0, then the right operand choose 10 instead of 0 because 0 is considered as false. So it's going again and again without stopping from blinking!
I better stop at 1, which will work.

11 April, 2006

split and regexp crossbrowser issue

Regexp are very powerfull when it comes to going deeper in string manipulation. However, in some cases, Internet Explorer and Firefow doesn't implement them strictly the same way. My best example is the following :
You want to split a string with several separators. This is well illustrated when splitting a date to get day, month, year and time info.
A Date in javascript prints as : Tue Apr 11 2006 17:15:27 GMT+0200
If you want to get all the infos, you can make:

var dateInfos = (new Date()).toString().split(/ GMT|[ :]/);
var day = dateInfos[0];
var month = dateInfos[1];
var date = dateInfos[2];
var year = dateInfos[3];
var hour = dateInfos[4];
var minute = dateInfos[5];
var second = dateInfos[6];
var offsetUTC = dateInfos[7];

So you get all the infos in one shot! This works with IE or Firefox.
Now imagine the first caracter of the splitted string is a separator:

var dateInfos = (' '+(new Date()).toString()).split(/ GMT|[ :]/);
var day = dateInfos[0];
var month = dateInfos[1];
var date = dateInfos[2];
var year = dateInfos[3];
var hour = dateInfos[4];
var minute = dateInfos[5];
var second = dateInfos[6];
var offsetUTC = dateInfos[7];

In this case, dateInfos[0] is empty in Firefox and 'Tue' is in dateInfos[1].
In IE, it remains the same as before, namely 'Tue' is in dateInfos[0].
And subsequently, the dateInfos Array is one element longer on Firefox than on IE.
So be carefull when you play with RegExp!
My best hack would be to ensure that the firsts caracters of the string are not a separator.