23 December, 2005

Transmitting arguments from a function to another

Lately, I was wondering how one could call a function from within another function and passing the arguments without knowing them. I point this out because it is very tricky to debug such a thing and Javascript already has the perfect hack to do that!
Try the following :

function test() {
return arguments.length;
}
test(1,2,3);

It returns 3 as espected.
Now try the call from within another function like this :

function test_in() {
test(arguments);
}
test_in(1,2,3);

It returns 1! Surprised ?
As arguments is just a special Array, it is transmitted to the test function as is.
So the test function receives only one argument which length is 3.
I have come up with the solution at the mozilla developer center.
The reserved words 'call' and 'apply' allow you to call a function in a different context than the function context. Using 'call', you give the context and the arguments, but using apply, you give the context and an array of arguments that becomes the arguments object of the called function! And that is just what we wanted.
Doing this :

function test_in() {
test.call(this, arguments);
}
test_in(1,2,3);

It doesn't solve the problem, but doing that :

function test_in() {
test.apply(this, arguments);
}
test_in(1,2,3);

It returns 3 as espected. Here is how javascript itself solves the nested blind call!

21 December, 2005

IE memory leak

Several articles have been published about the IE memory leak. One has come to the conclusion that the leak appear when two objects from different worlds (DOM vs Javascript) refer to each other. Here is an example :

myDom = document.createElement('DIV'); //DOM world
myJs = 'foo'; //JS world
myJs.dom = myDom; //First reference
myDom.js = myJs; //Second reference, creating a cycling reference

If you have this code in your page, you will see the corresponding iexplore.exe instance in your task manager increasing memory each time you reload . Here is the leak !

I have tried two things to avoid the leak, one was successfull.
The first thing I tried was to delete the reference from the Js object to the Dom object, writing this :

myJs.dom = null;

It doesn't work! So I decided to delete the reference from the Dom object to the Js Object :

myDom.js = null; // or myJs.dom.js = null;

And that worked. No more memory leak.
In conclusion, I have made up a reference cleaner which would delete Dom reference to Js objects before the page unload. That object is part of the Util class and is defined as follow :

Util.collector = new Array();
Util.collector.register = function(object) {
this.push(object);
}
Util.collector.empty = function() {
for (var i=0; i < Util.collector.length; i++)
Util.collector[i].dom.js = null;
}

each time you create a Js object that will refer to a Dom object, you register it to the collector by calling

Util.collector.register( myJs );

and somewhere in your code, you add :

window.onunload = function() { Util.collector.empty(); }

13 December, 2005

the Util class

Introducing the class Util. Its a metling pot of methods that can be very usefull at any time when programming javascript. Theses methods are not meant for a particular type of object. For example, the dollar function ($) which is a shorthand for document.getElementById is not part of the Util class. It is in the Dom class as it plays with DOM Elements.
Here are some methods :
//A shorthand for document.write
Util.dw = function(str) {
document.write(str);
}
//You can alert multiple arguments send to that function
Util.alert = function() {
var str = '';
for (var i=0; i< arguments.length; i++) {
str += arguments[i];
if ( i != arguments.length-1 )
str += ' / ';
}
alert(str);
}

12 December, 2005

the layerX property in Firefox

When an element is clicked, you can get the mouse relative coordinates from the top left edge of the element with the e.layerX and e.layerY properties in Firefox. I discovered that the Firefox team made a change from version 1.0 to 1.5. In Firefox 1.0, if your mouse is over the very first top-left pixel of the element (including the border if existing), these properties indicates (0,0) as Safari 1.3 does. But in Firefox 1.5, these are (1,1) ! And you know what, I like the second way better. Because if your element is 200px width, you get layerX from 1px to 200px instead of 0px to 199px as if it was an array index.
On IE, it's very different because the equivalent which is event.offsetX gives you the number of pixel from the left border excluding the border! So that you can get a negative value if your element is bordered. And from the first inside pixel, it works like Firefox 1.0, giving you a 0.
This time, I would give the vote for Firefox 1.5 which convince me the best.

09 December, 2005

Browser competition

Before going further in a framework implementation, I had a look at the Browser Statistics from w3schools. As they mention, it's only statistics, but I come up to the idea that my framework would be compatible with IE 6.0 and 7.0, Firefox 1.0 and 1.5, Safari 1.3 and 1.4 and Opera 8.5.
I will then gives you some feed back about cross-browser compatibility.
Let's begin with a simple example, the width style property of a DOM element.
Width is something abstract because from one browser to another, you don't see element the same size! In IE width is really what you see. It is the width of the element from one side to the other. In Firefox, width as a different meaning. It is the space available for displaying the child elements of a given element. On the screen, I would call it the internal width of an element. When you set the width of an element to a certain value, your element, from one side to the other as a total width of the value you specified plus the borders width plus the padding width.

Let's see an example of the width style property.

Introduction

I am developing web applications in Ajax technology for LUCCA. In the past days, I was asked to dig into the Ajax framework folk and to come up with ideas for our new application. The goal of this blog is to share my feed back on what I see on the web about Ajax framework. I will also try to present a bunch of functions that we could bring together to build a new framework.