29 December, 2006

workaround to make firebug console.log function bug free on IE

Firebug is very usefull for web development but its console only works great on Firefox for now.
If you want to keep console.log calls in your app event when your app is used on Firefox without the Firebug plug-in or on IE, you can add this line at the very first start of your JS code :

try { console.log('init console... done'); } catch(e) { console = { log: function() {} } }

This code tries to write some text in the Firebug console. If it fails (no Firebug plug in installed or under IE), it instantiate an object called 'console' that has a method called 'log' that does nothing !

05 December, 2006

BPM Counter

I have writtent a very, very simple tool for counting BPM of a song. All you have to do is to press the button when the bit happens. The value of the button indicates you the Bit Per Minute rate of you beeing a DJ !! Enjoy..

02 October, 2006

AJAX : le guide complet

A collegue and me have written a book about AJAX. It's integrally in french but the tutorials are in Javascript, so you might be able to understand them!

Description of the AJAX book
Buy our AJAX book at the best price!

09 August, 2006

Passing an object reference to a function

Here is another proof of Javascript spectacular flexibility. We want to draw 10 DIV in a page, representing 10 people. When we click a DIV, we want a message indicating which person was clicked. Given an object named person, we could hard code this doing :

div.innerHTML = person.firstName+' '+person.lastName;
div.onclick = function() {
alert(this.innerHTML+' was clicked');
}

But the object model would be useless in this case !
Our first try is to make a loop that creates 10 DIV and 10 objects and map each of it together. Let's look how it works :

<div id="myGroup" style="border: 1px dashed #000; padding: 5px; width: 300px;"></div>

And the script :

//A class Person
function Person( firstName, lastName ) {
this.firstName = firstName;
this.lastName = lastName;
}
//A function to be executed when onclick is fired
function clickFunction(person) {
alert(person.firstName+' '+person.lastName+' was clicked');
}
//We create 10 DIV representing 10 people
for (var i=0; i < 10; i++) {
//Create a DIV
var div = document.createElement('DIV');
//Create an object
var person = new Person('firstName'+i, 'lastName'+i);
//Fill in the DIV with the object infos
div.innerHTML = person.firstName+' '+person.lastName;
//Some styling
div.style.border = '1px solid #CCC';
div.style.margin = '5px';
div.style.cursor = 'pointer';
//Set the event on the DIV
div.onclick = function() {
//Use the object matched with the DIV in a function
clickFunction(person);
}
document.getElementById('myGroup').appendChild(div);
}

We have a DIV named myGroup which contains our 10 DIV
In each loop, we create a Person 'var person = ...' that is referred by the 'onclick' function of the DIV.
Try clicking on the people of MyGroup, you'll be quickly disappointed.
It refers to the last Person for any DIV we click on. WHY ?
Because the variable 'person' is re-written in each loop for a new Person. In the end, it lasts only 1 Person, person number 9!

One solution could be to push each Person in an Array and refer to the position of the Person in the 'onclick' function of the DIV. But Javascript has more to offer than this hack!
In Javascript, when a function creates a local variable that is refered by other functions, the variable is stored in memory until its last use.
We are going to exploit this capability like this :

//A class Person
function Person( firstName, lastName ) {
this.firstName = firstName;
this.lastName = lastName;
}
//A function to be executed when onclick is fired
function clickFunction(person) {
alert(person.firstName+' '+person.lastName+' was clicked');
}
//A function that is used to create a DIV matched with an object
function createDiv(index) {
//Create a DIV
var div = document.createElement('DIV');
//Create an object
var person = new Person('firstName'+index, 'lastName'+index);
//Fill in the DIV with the object infos
div.innerHTML = person.firstName+' '+person.lastName;
//Some styling
div.style.border = '1px solid #CCC';
div.style.margin = '5px';
div.style.cursor = 'pointer';
//Set the event on the DIV
div.onclick = function() {
//Use the object matched with the DIV in a function
clickFunction(person);
}
document.getElementById('myGroup').appendChild(div);
}
//We create 10 DIV representing 10 people
for (var i=0; i < 10; i++) {
createDiv(i);
}

What we do here is to create an intermediate function that aims to create local variables. Now the variable 'person' is stored at each loop, event if it has the same name! And each 'onclick' function refers to the right 'person'.

15 June, 2006

IE AJAX memory leak

We already know about IE memory leak pattern. It's a matter of garbage collection between JS objects and DOM objects.
Did you know about IE HttpRequest memory leak ??
It seems that there is the same symptom with HttpRequest object instanciation. In IE, that objetc is not JS native. It is an ActiveXObject. So that might be the cause.
I have recently faced important memory leaks in our new AJAX application. However, I had my own implementation working well for breaking DOM and JS cycling reference. The point was that my HttpRequest objets where refering to a higher level JS object that contained an array with references to these HttpRequest objets. So I had a cycling reference between standard JS object and ActiveXObject. I did the same breaking reference tool and it all disappeared!

24 April, 2006

AJAX training seminar

I am currently in Chicago for the next Pragmatic Studio! That training will help me preparing our own AJAX seminar taking place in Paris next month. If you are interested in such training, you can subscribe online.
The next step is to write a book talking about AJAX. It's an "AJAX from scratch" book written for personal users. We will shortly release the full table of content in order to get feedback before going further with the work.

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.

16 March, 2006

Numbers versus int values

In javascript, it is very usefull than one can prototype primary classes like String, Array or Date.

Lot's of Ajax Frameworks do it. Prototype for example adds a 'return length;' command to the push Array method so that you can push an element into an array and get the new size in the while.

In Ruby, you have the possibility to call integer methods to tell the script to do something special. For example if you want to do a loop 10 times, you can use the expression 'for 10.times'. You se that the method (or attribute) is attached directly to someting that looks like an integer. It doesn't event seem to be an object.

In Javascript, it's different. You cannot call a method directly from an integer value. But you can do it from an object of class Number.
Take the example of date attributes (day, month, year) that are numbers. You want to display them on the screen within a 2-digit format like this : '03/15/06'
If you call theDate.toString() you get '3/15/2006' because they are numbers.
Let's prototype the class String first and then Number :

//Repeat a string 'many' times
String.prototype.repeat = function(many) {
var s = '', t = this.toString();
while (--many >= 0) s += t;
return s;
}
//Left fill a number with zero so that the result has a length of 'many'
Number.prototype.addZero = function(many) {
return ('0'.repeat(many) + this.toString()).substring(('0'.repeat(many) + this.toString()).length - many);
}

And now you can do :

var i = 5;
i.addZero(10); //You get the string '0000000005'
OR (new Number(5)).addZero(10);
BUT NOT 5.addZero(10);

What is cool is that any integer value return by the javascript primary classes is a real Number and not just an integer. So for dates formatting, you can use the following :

Date.prototype.toFullString = function() {
return this.getDate().addZero(2) + '/' + (this.getMonth()+1).addZero(2) + '/' + this.getFullYear();
}
}

Pretty cool hun ?!

17 February, 2006

DOM vs LDOM

I would like to introduce some ideas about our vision of the framework.
Lot's of Ajax frameworks come with cross-browser compatibility. That's a good point. But still they are working with DOM Element.

We introduced new elements called LDOM Element.
The priniciple is that for each important DOM Element on the web page, you have a corresponding LDOM Element.
From your script, you don't "speak" to DOM Element anymore, but with theses LDOM Elements. Beyond that, LDOM Element are pure Javascript Objects so they are faster to query.
I have made up a mere example of a property access to a DOM Element and to the same DOM Element, but through the LDOM Element. This is made possible because the LDOM Element listen to the changes of it's DOM and update it's value.
Let see DOM access vs LDOM access.

31 January, 2006

the wonderfulness of eval( ) and setTimeout( )

If have been diggin' into delaying code execution without context loss.
One knows that when using setTimeout, you loose the context you where in when calling that function.
The idea is to make javascript take a picture of the context, wait, wait, then execute some code in that memorized context. Plus, I want the way to do that being easy to understand and natural to write.
So I came up with a couple of functions, each with a certain role to play:
1. We need a global variable that stack the contexts and unstack them when time is out!
2. We need an easy way of writing code to be executed.
The solution here is to encapsulate the code within an anonymous function that we will call when time is out within the unstacked context! Wonderful, isn't it ?
And here comes the code:

//A function that returns unique IDs
//(it's like a class with a class attribute)
getId = function() {
if (!this.id)
this.id = 0;
this.id++;
return this.id;
}
//A function that acts like a stack (registers objects by unique IDs)
registerObject = function(objType, id, o) {
if (!this.objById)
this.objById = new Array();
if (!this.objById[objType])
this.objById[objType] = new Array();
if (this.objById[objType][id])
alert('Object already registered with this ID!!');
else
this.objById[objType][id] = o;
}
//A function that unstacks the registered object with a given ID
getObjectById = function(objType, id) {
return this.objById[objType][id];
}
//We use objType for our stack to be reusable
//in other parts of our program
//This way, the stack can hold several object in different use contexts
//A test class to be instantiate
testClass = function() {
//Attribute
this.phrase = 'Cool! The context is saved!';
//Method with reference to the class object
this.doSomething = function() {
alert(this.phrase);
}
}
//The function that delay code execution
delay = function(code, contexte, time) {
//We provide a unique ID for our context object to be memorized
var id = getId();
//We register our context object in the stack
registerObject('delay', id, contexte);
//When time is out, the code will be evaluated within the stacked context
setTimeout('eval('+code+'.call(getObjectById(\'delay\','+id+')));', time);
}
//Then we run the test!!
//Instantiate the test class
var myTest = new testClass();
//Call a method right now
myTest.doSomething();
//Call the same method in 5 secondes
delay(function() { this.doSomething(); }, myTest, 5000);

And the magic operates!

18 January, 2006

width percentage issue


In a previous post
, I already pointed out the difference between IE and Firefox concerning the width property when set in pixel.
It appears to work the same way when this property is set in percentage.
Indeed, try setting the width of a bordered DIV to 100% of the BODY. For example, the DIV has a classic 1px black border. The body, depending of your screen resolution and the size of the IE (or Firefox) window, could be 950px large. On IE, you get a DIV which width is 950px (948 + 2 for the borders). That's what you expect, right ?
On Firefox, you get a DIV which width is 950px. But remember, on Firefox, the padding and border are not included, so you get a border-to-border width of 952px (950 + 2 for the borders) and a hugly horizontal scrollbar at the bottom of the page. Plus, you don't see the right border of your DIV ! That's not really what you expected !?
See my width percentage issue sample for the visual proof.

04 January, 2006

HTML, DOM and Ajax Features

Thinking about the HTML tree and the DOM capabilities, I come to the conclusion that you can very easily apply an Ajax feature to several HTML element at the same time. What you need is to have a common parent for them and apply the feature to the parent. If the parent moves, fades, resizes, disappear, change font style, etc... the children elements will act the same.
What if you want to fade a thumbnail of a picture once the picture is faded ? God, you have to write specific code to indicate to fade the thumbnails each time a related picture is faded!
To me, it's a big lack in HTML that you cannot group elements otherwise than in a tree style. Worse, doing so, HTML tags are used both ways : for graphic rendering and for encapsulation. Think about two HTML DIV you want to move together. You will create a tird DIV that contains them. First two DIV : graphical ; Tird DIV : encapsulation.

<div id="I'm here for non graphical reason">
<div>First DIV</div>
<div>Second DIV</div>
</div>

In our framework, we introduce a non graphical element that contains graphical elements and responds to Ajax features as a graphical element would. This way, it is transparent for the developper to apply a feature to a graphical or a non graphical element. And there is NO DOM element which are used for feature managment.

firstDiv = new LDivElement('first', 'First DIV');
secondDiv = new LDivElement('second', 'Second DIV');
group = new LDomListElement(firstDiv, secondDiv);

See the difference between the two classes LDivElement and LDomListElement while in HTML it's always HTMLDivElement.