Miscellaneous Tricks and Tips.

  1. Setting the top and left values of positioned elements with CSS units, when needed
  2. Using function references with setTimeout and setInterval

Setting the top and left values of positioned elements with CSS units, when needed

When setting the position of a positioned element by assigning values to the CSS top and left properties of the element's style object it is necessary to provide the value as a string with the units of the length (usually "px") following the value. Modern standards compliant browsers require this, older and more tolerant browsers may assume that values without units represent "px" units but they can handle string values which include the CSS units. Unfortunately some browsers want the top and left values provided as numbers and complain (or don't react) if they are provided as strings with units.

A technique for handling this requirement is based on the observation that when a browser expects the top and left values to be set as a number of pixels a typeof test of either the top or left properties will return "number" while if that same test returns "string" the browser either will require the CSS units to be appended to the values set as a string or it will successfully handle a value in that format.

Once the object on which the top and left values are to be set is available one of its top or left properties can be tested with tyoeof and an appropriately scoped variable set to either the string "px" or the number zero.

var cssUnitsOrZero = (typeof styleObjectRef.top == 'string')?'px':0;

Then when the position has been calculated (as a number) it can be assigned to the appropriate property with the value derived as the result of the test applied to it using the + operator. Because the + operator is a duel role addition and string concatenation operator, and decides which action it will take based on its operands, the application of the + operator to a position value as a number will depend on the type of the value derived from the preceding typeof test on the top or left properties.

styleObjectRef.top = numericPosition + cssUnitsOrZero;

/* If the - numericPosition - value was 125, for example, and - 
   cssUnitsOrZero - was zero, the value assigned would be:-

 styleObjectRef.top = (125 + 0);

   - which is the number 125. If - cssUnitsOrZero - was "px" then
   the assignment would be:-

 styleObjectRef.top = (125 + "px");

   - which is the string "125px".
*/

If the tested top property was not a string cssUnitsOrZero will be the number zero and the + operator will have two numeric operands and will perform numeric addition, assigning a numeric value to the property, unmodified by the addition of zero. But if the tested property was a string, so cssUnitsOrZero was assigned the string value "px", the + operator will recognise that one of its operands is a string and type-convert the other (the calculated position value) into a string and perform concatenation, appending the "px" CSS units string to the string representation of the calculated position and then assign that value to the property.

This fulfils the requirement to provide CSS units where needed while providing the vlaues in numeric form whenever that is the type of value expected. It is inefficient to perform the typeof test on a relevant property whenever a value is to be assigned, it is better to perform the test once and then re-use the same cssUnitsOrZero variable for all subsequent assignments.

Using function references with setTimeout and setInterval

The setTimeout and setInterval functions provided by web browsers are commonly used with a string of javascript source code as their first argument, frequently a string that does no more than call a separately defined function:-

function invokedWithSetTimeout(){
    ... // do something.
}
...
var timer = setTimeout("invokedWithSetTimeout()", 100);

The string argument is interpreted and executed after the interval specified as the second argument (in milliseconds). In the preceding code the invokeWithSetTimout function would be called.

On more recent browsers (easily the majority these days) the first argument to the setTimeout and setInterval functions can be a reference to a function. Instead of having to interpret and execute a string of javascript source code the function referred to is just executed after the interval. That will be more efficient as considerably smaller overhead would be involved in the execution of the function.

var timer = setTimeout(invokedWithSetTimeout, 100);

Unfortunately a number of older browsers such as IE 4 and Opera 5 do not understand the function reference versions of setTimeout and setInterval, leaving the use of string arguments as apparently the best method for cross-browser support. However, it is in the nature of loosely typed javascript that when a native code function such as setTimeout/Interval is expecting a string argument but is instead passed a value of another type that value will be type-converted into a string. That doesn't help much when the process of type-converting a function into a string results in an implementation dependent representation of the function, as is normally the case.

Type-converting of a function to a string is done with the function's toString method, usually Function.prototype.toString. Methods of a prototype can be overridden by methods of the function object itself and an overriding toString method can return any value its creator desires. That fact provides a means of using the more efficient function reference arguments with setTimeout/Interval and still supporting browsers that can only handle string arguments, by assigning a custom toString method to the function that is referred to in the argument to setTimeout/Interval. That custom method would return the string that would have been used in the setTimeout/Interval function call. If the function reference is type-converted to a string that string represents the javascript source code that would be needed to invoke the function. If it is not type-converted then setTimeout/Interval can invoke the function directly (and without the overhead involved in interpreting and executing the string of source code).

function invokedWithSetTimeout(){
    ... // do something.
}
/* Assign a function expression to a toString property of the function
   object referred to by the identifier - invokeWithSetTimeout -,
   overriding - Funciton.prototype.toString -. The new toString
   function returns the javascript source code needed to invoke a call
   to the function.
*/
invokedWithSetTimeout.toString = function(){
    return "invokedWithSetTimeout();";
}
...
var timer = setTimeout(invokedWithSetTimeout, 100);
/* If the browser will only recognise string values as the first
   argument to - setTimeout - then the function referred to by the
   identifier - invokeWithSetTimeout - will be type-converted to a
   string by calling its - toString - method, which will return the
   string " invokedWithSetTimeout();" and that string will
   be employed by the setTimeout function. Efectivly the same as
   calling the setTimeout function as:-
   
var timer = setTimeout("invokedWithSetTimeout()", 100);
*/

comp.lang.javascript FAQ notes T.O.C.