Javascript - Useful Tips & Tricks


#1

Let's have them smile


#2

1)
Include js version in the language attribute, e.g.
<script type="text/javascript" language="JavaScript1.4">

Useful if you want to "hide" code from older browsers
E.g. if you use try...catch statements (v 1.4)

2)
Use try...catch to catch exceptions


#3

Ok. What I'm about to relate aren't necessarily rules to be obeyed or anything like that, but just stuff that I've learned from my own experiences with coding javascript that, well, make my life easier.

Variables
Always declare variables with var this is just good consistency, and not doing so CAN cause errors in certain situations (it's a scope issue).

End of lines
Please, use semicolons. I know javascript doesn't require them, but use them anyways. It makes code easier to read and EVERY other C-based scripting language requires them

Functions and parameters
Whenever possible, use a function. Likewise, if something is variable, use a parameter. Functions and parameters are the basic building blocks for any successful javascript...er...uh...script.

Share the workload
It may seem ironic at first, but 3 short functions are more efficient than one long procedural function. Especially if tasks get repeated. This becomes more important if you start making methods and objects of your own.

Global variables
Did you know that all global variables are also properties of the window object? They are! What does this mean? Well, it means that we can create global variables from inside a function. In fact, let's make a function that exists JUST to create new global variables

function makeNewGlobal( varName, val )
 {
 	window[varName] = val;
 }
 
 makeNewGlobal( "greeting", "Hello World!" );
 alert( greeting ); // Alerts 'Hello World!'

This concept should go hand-in-hand with the previous topic, Functions and Parameters.

Create references
If you have any code that accesses a DOM object that you need to use more than once, create a reference. It's for more efficient than running getElementbyId() a bunch of times, or accessing your object via some collection such as [images or [url="http://msdn.microsoft.com/workshop/author/dhtml/reference/collections/links.asp"]links](http://msdn.microsoft.com/workshop/author/dhtml/reference/collections/images.asp). Example

// Bad way
 function changeObject( oId )
 {
 	document.getElementById( oId ).className = 'blah';
 	document.getElementById( oId ).setAttribute( "alt", "new text" );
 }
 
 // Good way
 function changeObject( oId )
 {
 	var o = document.getElementById( oId );
 	o.className = 'blah';
 	o.setAttribute( "alt", "new text" );
 }

For those of you that don't know, my variable o is not a copy of the object or anything like this, but just a label of sorts with which I can use it to address the object it's referencing. (don't use the with statement)

The parseInt() function
A very handy function indeed, but what happens here?

var myString = "010";
 var myNum = parseInt( myString );

Does myNum now equal 10? Noooo. myNum is now equal to 8. Why? Becase parsenInt does it's best to guess the proper radix based on the input (8, 10, or 16), and a number like 010 looks octal. It's the leading zero in the string that trips up parseInt() here. It is not very well known that parseInt can take a second parameter. You guessed it, the radix.

var myString = "010";
 var myNum = parseInt( myString, 10 );

This gives us what we expect, myNum is now equal to 10.

For loops
Always initialize each variable you need, rather than calling on a property in the loop's conditional. For example, instead of this

var myString = "Hello";
 for ( var i = 0; i < myString.length; i++ )
 {
 	alert( myString.charAt( i ) );
 }

Use this

var myString = "Hello";
 for ( var i = 0, len = myString.length; i < len; i++ )
 {
 	alert( myString.charAt( i ) );
 }

This way, the myString.length property is retrieved only once, and not at each iteration of the loop. Ok, now for my favorite way to do For loops of this nature. Did you know that when you assign a variable a value there is also a return value? That return value is a Boolean indicating if the data was succesfully stored into the variable or not. <EDIT> See notes regarding this statement in the posts below </EDIT> If you need to retrieve a value from the array or string (like above) then your for loop can look like this

var myString = "Hello";
 for ( var i = 0; ( c = myString.charAt( i ) ); i++ )
 {
 	alert( c );
 }

Remember, the middle portion of the for loop just needs to evaluate as true for the loop to proceed. Neat, eh?

While loops
I won't say much here, but if you are performing some type of breaking condition inside a For loop, you probably need a while loop instead.

Switch statements don't have to break after each case
Sometimes the pesky behavior of [switch statements can be a blessing. Imagine that I wanted you to create a function then when passed an integer between 0 and 10 would return a countdown-style string? How would you do it? If you remembered that switch statments proceed until they see a [url="http://msdn.microsoft.com/library/en-us/script56/html/js56jsstmbreak.asp?frame=true"]break](http://msdn.microsoft.com/library/en-us/script56/html/js56jsstmswitch.asp?frame=true), you might use one something like this

function blastoff( timer )
 {
 	var notice = "";
 
 	switch( timer )
 	{
 		case 10 : notice += "Ten, ";
 		case 9 : notice += "Nine, ";
 		case 8 : notice += "Eight, ";
 		case 7 : notice += "Seven, ";
 		case 6 : notice += "Six, ";
 		case 5 : notice += "Five, ";
 		case 4 : notice += "Four, ";
 		case 3 : notice += "Three, ";
 		case 2 : notice += "Two, ";
 		case 1 : notice += "One, ";
 		case 0 : notice += "Zero, ";
 		default : notice += "Blastoff!";
 	}
 	return notice;
 }
 
 alert( blastoff( 10 ) );
 alert( blastoff( 5 ) );

Our first alert gives us "Ten, Nine, Eight, Seven, Six, Five, Four, Three, Two, One, Zero, Blastoff!" and our second alert gives us "Five, Four, Three, Two, One, Zero, Blastoff!". Simple, huh?

Popup Window Links
If you are making a link to a popup window, I highly suggest this format

<a href="whateverPage.htm" target="new" onclick="window.open( this.href, this.target, '[i]whatever features you want here[/i]' ); return false;">Click here!</a>

This differs somewhat from using the java script: pseudo-protocol or just putting a hash (#) in the href. The method above will still allow the link to be usable if the user has javascript turned off and more importantly, search engine spiders can follow this link

Use bubbling to your advantage
Let's say that you have about 100 images onto which you want to apply some events, like onmouseover and onmouseover for a rollover-type className change. Instead of attaching each event to each image, use the events bubbling to make your life easy.

<script type="text/javascript">
 function doRollover( e )
 {
 	// Obtain a reference to the lowest element
 	var o = ( document.all ) ? event.srcElement : e.target;
 
 	// If the element is not what we want, quit the function
 	if ( o.nodeName != 'IMG' ) return;
 
 	// Perform rollover
 	o.className = ( o.className == 'overClass' ) ? 'outClass' : 'overClass';
 }
 </script>
 
 <!-- Now for the interesting part -->
 <div onmouseover="doRollover()" onmouseout="doRollover()">
 	<img src="blah.gif" class="outClass" />
 	<img src="blah2.gif" class="outClass" />
 	<img src="blah3.gif" class="outClass" />
 <!-- Etc, etc -->
 </div>

Confused? Well, because both the onmouseover and onmouseout events bubble, that means that the DIV that contains all our images is hit with the events too, so we can capture thm there, and filter out the events that we don't want, and keep the ones we do.

Creating HTML strings
If you are creating HTML as a string whether performing an innerHTML operation or whatever, use single quotes to delimit the HTML string. Why? Because proper HTML should have double quotes around attribute values, and using single quotes to delimit the HTML keeps you from having to do lots of escaping.

Regular Expressions
Learn them. Love them. Use them. Get some links here

Consult your references
Always check with documented sources if you are unsure about something. I once spent 2-3 minutes creating a function that would reverse all the items in an array. Lo and behold, the reverse() method for arrays has been around since version 3 browsers.

A Constructor constructor
Here's a neat little trick for you advanced JS folks out there. Ever wanted to create your own object without having to define a unique constructor function? Well, you can! Check this out...

function ClassConstructor( props, methods )
 {
 	var prop, meth, fstr='';
 	for ( var p=0; (prop = props[p]); p++ )
 	{
 		fstr += 'this.' + prop + '=' + prop + ';';
 	}
 	for ( var m=0; ( meth = methods[m] ); m++ )
 	{
 		fstr += 'this.' + meth + '=' + meth + ';';
 	}
 	return new Function( props, fstr );
 }
 
 function pricePerUnit()
 {
 	return Math.round( ( this.price / this.quantity ) * 100 ) / 100;
 }
 
 dataprops = ['id','name','price','quantity'];
 datamethods = ['pricePerUnit'];
 
 var ShoppingItem = new ClassConstructor( dataprops, datamethods );
 var myData = new ShoppingItem( 1, 'x-widget', 9.99, 12 );
 alert( "The " + myData.name + " has a per unit cost of $" + myData.pricePerUnit() + " dollars." );

Well, I'm sure if I sat here long enough I could come up with a dozen more things, but hey, you guys got what came to my head today

Edit:

2003.08.15 - Two new tips posted!

Conditionals
If you are doing some sort of comparison conditional, where one operand of that conditional is a literal, like if ( someVar == "someString" ) or if ( myNum == 3 ), it's actually better to list the literal operand first:

if ( "someString" == someVar )
if ( 3 == myNum )

Why? Because if you mistype the equality operator (==) and instead type the assignment operator (=) -- a fairly common typo, then you will discover this error at runtime. Tracking down the cause of these errors can be difficult, but switch the order of your operands and the mistake of assigning a variable to a literal error instantly and give a useful line-number (even in IE!)

The hidden power of setTimeout
For some reason, many, many, MANYpeople don't know that the first argument for the setTimeout (and setInterval) function doesn't have to be a string. In fact, it is much more powerful when you send a function pointer, or, a reference to a function (passing it by name), instead.

So, instead of

setTimeout( "loop()", 1000 );

do it this way

setTimeout( loop, 1000 );

Now, if we get creative, we can solve the issue of passing arguments to a setTimeout-called function, which I've seen many times. As I'm sure some of you know, the variables you are trying to pass will lose scope (unless they are global). The method to our madness will be the anonymous function.

Once again, instead of

setTimeout( "loop(counter)", 1000 );

We use

setTimeout( function() { loop(counter); }, 1000 );

I know what you're thinking -- "Why can't I use setTimeout( loop(counter), 1000 ) ???". I'll tell you why: because that, my friend, is a function call, and if you remember, I said we need to pass a function pointer. Since we declare an anonymous function that itself calls loop(), then we are legitimately passing the proper reference, AND maintaining the power to call the function. It's like having your cake and eating it too!

Here endeth the tips.

Enjoy, and happy coding

Edit:

Re: jofa's post. Although I agree with the concept of hiding javascript from browsers that don't support it, I think it's important to note that XHTML 1.0 Strict does not allow for the language attribute on SCRIPT elements

#4

Originally posted by beetle

// Good way
function changeObject( oId )
{
    var o = document.getElementById( oId );
    o.className = 'blah';
    o.setAttribute( "alt", "new text");
}

Impressive list of tips smile

The "Create references" tip is especially good, because it's very common that people use the Bad way of coding

Just wanted to add: you can use a with statement when you work with properties/methods of an object

with(o)
{
  className = 'blah';
  setAttribute("alt", "new text");
}

Can make the code easier to read too:

with(Math)
{
  myVar = abs(sin(x) * PI + cos(y) / E);
  // compare to
  // myVar = Math.abs(Math.sin(x) * Math.PI + Math.cos(y) / Math.E);
}

#5

Originally posted by beetle
Did you know that when you assign a variable a value there is also a return value? That return value is a Boolean indicating if the data was succesfully stored into the variable or not.

Somebody's got to do it. That statement is incorrect. The return value is whatever was assigned.

Type this in your location bar:
javascript:alert(window.myprop = 'hi')

You'll get an alert with the message "hi".

You can do compound assignments:

myVar1 = myVar2 = myVar3 = "some value";

because of this fact (assignment goes from right to left, so it works out).

The reason your charAt() loop ends is because:

"hello".charAt(10) == ''

An empty string. And an empty string typecasts into a boolean true value, which is what is happening at the end of each iteration in your loop.


#6

Thanks for the clarification jkd.

I realize now that I improperly worded what I was trying to convey: That a variable assignment can be tested for true/false value to control a FOR loop.

Note to other readers: you can forcefully retrieve a boolean value and still assign the variable like this...

javascript:alert( Boolean( window.myprop = 'hi' ) );


#7

Whats the difference between?
[list=1]
[*]JavaScript
[*][B]ecmaScript[/B]
[*]JScript
[/list=1]

JScript was origionally based on netscape documentation, but due to features and functionality was not re-created by Microsoft properly, which resulted in discrepancies between jscript 1.0 and javascript 1.1. Since then JavaScript was submitted and has become known as ecmaScript(ECMA-262). Because of this standardization, it is now perceived that javascript is Netscapes implementation and Jscript is Microsofts...
23
JavaScript
ecmaScript
JScript

Objects Hierarchy...

Window
+-Frame
+-Document
+-+
  +-Layer
  +-Link
  +-Image
  +-Area
  +-Anchor
  +-Applet
  +-Plugin
  +-Form
  +-+
    +-Textarea
    +-Text
    +-FileUpload
    +-Password
    +-Hidden
    +-Submit
    +-Reset
    +-Radio
    +-Checkbox
    +-Button
    +-Select
    +-+
      +-Option
+-Location
+-History

+-Navigator
+-+
  +-Plugin
  +-MimeType

Syntax

Syntax::Semicolon :- As mentioned previously this can affect the way a script is executed. Heres a quick example why...

<script type="text/javascript">
for (a=0,b=10;a<b;a++) document.write (a);
document.write ("\
<br/>");  //line break
for (a=0,b=10;a<b;a++); document.write (a);
</script>

Syntax::ScriptTag :- Use

<script type="text/javascript">
  /* code */
</script>
or
<script src="http://www.mydomain.com/default.js" type="text/javascript">
</script>

Syntax::Strings :- Escaping characters are...

<script type="text/javascript">
  /*
    \\b  = Backslash
    \
  = Newline
    \\r  = Carriage return
    \\'  = Single quote
    \\"  = Double quote
    \\\\  = Backslash
  */

  var escapechars = '\\b<br />\
<br />\\r<br />\\'<br />\\"<br />\\\\';
  document.write (escapechars);
</script>

[Explain]
Post - Increment...
Pre - Increment...
Post - Decrement...
Pre - Decrement..

Syntax::Switch :- Instead of using long winded if statements use a switch/case statement

<script type="text/javascript">
  //Declare Variable
  var a = 1;

  switch (a)
  {
    case 1 : document.write(1); break;
    case 2 : document.write(2); break;
    case 3 : document.write(3); break;
    case 4 : document.write(4); break;
    case 5 : document.write(5); break;
  }
</script>

<script type="text/javascript">
  //Declare Variable
  var a = 1;

  //use a conditional switch over multiple if else statements

  switch (a)
  {
    case (a == 1 || a == 2)  : document.write('1 or 2'); break;
    case (a == 3 || a == 4)  : document.write('3 or 4'); break;
    case (a == 5 || a == 5)  : document.write('5 or 6'); break;
    case (a == 7 || a == 8)  : document.write('7 or 8'); break;
    case (a == 9 || a == 10) : document.write('9 or 10'); break;
  }
</script>

<script type="text/javascript">
  //Declare Variable

  //use a conditional switch over multiple if else statements
  //theres no need to declare a variable just replace the switch expression with true
  // missing out the break condition allows the condition to fall through to the next statement.

  switch (true)
  {
    case (a == 1 || a == 2)  : document.write('1 or 2');
    case (a == 3 || a == 4)  : document.write('3 or 4'); break;
    case (a == 5 || a == 5)  : document.write('5 or 6'); break;
    case (a == 7 || a == 8)  : document.write('7 or 8'); break;
    case (a == 9 || a == 10) : document.write('9 or 10'); break;
  }
</script>

<script type="text/javascript">
  //Declare Variable

  //Continue, statement force the condition to start at the beginning of a loop

  switch (true)
  {
    case (a == 1 || a == 2)  : document.write('1 or 2'); break;
    case (a == 3 || a == 4)  : document.write('3 or 4'); break;
    case (a == 5 || a == 5)  : document.write('5 or 6'); break;
    case (a == 7 || a == 8)  : document.write('7 or 8'); break;
    case (a == 9 || a == 10) : document.write('9 or 10'); break;
  }
</script>

will continue to edit...


#8

Awesome tips!

Here's one that will really help with debugging:

If you are using Netscape, Mozilla, or any other browser that that uses the Gecko rendering engine (correct me if I am wrong on that wink), simply type this into your address location:

java script: (no space between java and script)

That should display a debugger.


#9

Just a note on the JS with statement...I've seen quite a number of advanced programmers (with wide experience in OOP) state, unequivocally: "Don't use it." It jiggers the scope chain, can produce unwanted results, and is almost always unnecessary. From the above:

M = Math;
{
  myVar = M.abs(M.sin(x) * M.PI + M.cos(y) / M.E);
}

You can, of course, add static Math functions/constants of your own to streamline coding.

People who use with seem to use eval() a lot too. wink


#10

Something for the plebs such as myself...

window.onload=functionName(); in embedded or external javascript :tup:

<body onload="functionName();"> :tdown:

Very useful method for implementing automatic post-load functions sitewide whilst helping to keep the code and markup even more separated (which is :tup: :tup: :agree: )


#11

I actually disagree. Although the advice is well-intentioned, it can ultimately cause many problems.

First of all, to properly do script-loaded javascript functions - you must assign a function pointer to the onload event, and not a function call.

window.onload = functionName;

Notice, no parentheses. However - what happens when you have two or more scripts that both do the same thing? Well, the event-assignment that comes latest in source order will override any previous declarations - just like over-writing a variable.

Solutions? Well, one can adopt the new methods for aggregating events onto a handler, such as Microsoft's attachEvent() and the W3C-approved addEventListener(). However, these do not come without their own stigmas. First, you must write an abstraction or sniffer-type mechanism to make sure each browser uses the method it supports. Second, even then, some browsers don't support either method (such as IE-mac, and NS4).

I find the easiest and most compatible solution is to combine all onload function-calls int a common init() function. Every browser with JS support can see/use it, and it's super-easy to setup. Just take all your onload script events and move them like this

function init()
{
  function1();
  function2();
}

Etc. This also allows you to send parameters to your function much easier than using either method discussed above (which would involve another abstraction or using anonymous functions). The next step is to make sure you the body tag's onload event points to init() and that any window.onload events point there as well

window.onload = init;
 
-or-
 
<body onload="init();">

If you have several assignments, it doesn't matter, because you are just assigning the same value.

That is all (for now) smiley


#12

And that's why you've got the orange badge and I ain't. wink

fwiw, I meant window.onload = functionName; but force of typing habit made me put the parentheses in.

I'll read the rest of your post when my heads in that place (which is clearly wasn't when I wrote mine) wink

[edit]
discounting my () typo, there's nothing about my post that precludes its use as the final init call.

I didn't say that several functions should all be lined up on the back of the precursive window.onload call. I just gave it as a one-shot example.

My suggestion was merely about dealing with the onload event and how best to address it for site-wide functions whilst keeping code and markup as separate as possible.

Had I found the need to call several onload functions I surely would have done the same as you and wrapped them all into another function and called that function during the window.onload call.

Still, as I said, my example does not preclude its use in the form of your init/init() example.
Your example purports to debunk mine only to end up in the same place, giving the same options, one of which is preferable to the other- the illustration of which was the sole purpose of my original post.
[/edit]


#13

Fair enough. I just wanted to make sure those reading this understood possible complications - particularly because using window.onload = functionName; is one of if not THE primary cause of javascript conflicts.

In the end, the ability to aggregate events is the most desirable choice - but the tech isn't quite there yet to make it a "best" solution.


#14

phew

For a moment there I thought I might have to admit that I was wro! that I was wr! wron!

Dammit! I can't even bring myself to say the word!

wink

Kudos to ya, Beetle.


#15

Hey Bettle Shouldnt this

function ClassConstructor( props, methods )
{
	var prop, meth, fstr='';
	for ( var p=0; (prop = props[p]); i++ )
	{
		fstr += 'this.' + prop + '=' + prop + ';';
	}
	for ( var m=0; ( meth = methods[m] ); i++ )
	{
		fstr += 'this.' + meth + '=' + meth + ';';
	}
	return new Function( props, fstr );
}

function pricePerUnit()
{
	return Math.round( ( this.price / this.quantity ) * 100 ) / 100;
}

dataprops = ['id','name','price','quantity'];
datamethods = ['pricePerUnit'];

var ShoppingItem = new ClassConstructor( dataprops, datamethods );
var myData = new ShoppingItem( 1, 'x-widget', 9.99, 12 );
alert( "The " + myData.name + " has a per unit cost of $" + myData.pricePerUnit() + " dollars." );

Be This

function ClassConstructor( props, methods )
{
	var prop, meth, fstr='';
	for ( var p=0; (prop = props[p]); <font color='red'>p</font>++ )
	{
		fstr += 'this.' + prop + '=' + prop + ';';
	}
	for ( var m=0; ( meth = methods[m] ); <font color='red'>m</font>++ )
	{
		fstr += 'this.' + meth + '=' + meth + ';';
	}
	return new Function( props, fstr );
}

function pricePerUnit()
{
	return Math.round( ( this.price / this.quantity ) * 100 ) / 100;
}

dataprops = ['id','name','price','quantity'];
datamethods = ['pricePerUnit'];

var ShoppingItem = new ClassConstructor( dataprops, datamethods );
var myData = new ShoppingItem( 1, 'x-widget', 9.99, 12 );
alert( "The " + myData.name + " has a per unit cost of $" + myData.pricePerUnit() + " dollars." );

I Could be wrong though!


#16

Yes - I changed up the 'i's to be 'm's and 'p's because they were messing w/the italics (vBcode) Thanks for catching my goof!

smiley


#17

hi frnz,

The posts are really good and useful fo the usage.

Can any one of you please tell me how can i make any file downloadable. so i need to use any specific tag or javascript function which will be invoked on any event like onclick, etc.
I know that i can give a link to a file of unknown extension and it will ask for the download but if i want to make a HTML file to be downloadable.

Thanks.
Vikrant.


#18

Actually, vikrantkorde, you can't do that with Javascript - you'll need to use PHP to send the proper HTTP headers.


#19

Here Is A Script I Designed Myself For Geting The Search String

// CREATED BY SCOTT DENNISON
// [http://Scottie_Too_Hottie7.tripod.com](http://scottie_too_hottie7.tripod.com/)
/* ---------------------------------------------------------------------- *\\
  Function	: URL_GetLength
  Description : Find How Many Times The Name Appears In The location.search String
  Usage	   : URL_GetLength(name)
  Arguments   : name - The NAME out of NAME=VALUE
\\* ---------------------------------------------------------------------- */
function URL_GetLength(name) {
var occurences = 0;
var sections = location.search.substr(1).split("&")
for (i=0; i<sections.length; i++) {
var sectionsplit = sections[i].split("=")
if (sectionsplit[0] == name) {
occurences++
}
}
return occurences;
}
/* ---------------------------------------------------------------------- *\\
  Function	: URL_Exists
  Description : Find Whether The NAME Exists In The Search String
  Usage	   : URL_Exists(name)
  Arguments   : name - The NAME out of NAME=VALUE
\\* ---------------------------------------------------------------------- */
function URL_Exists(name) {
if (URL_GetLength(name) == 0) {
return false;
}
return true;
}
/* ---------------------------------------------------------------------- *\\
  Function	: URL_Return
  Description : Returns The Value If There Is Only One Occurence Of NAME
	Returns An Array Of Values In There Are More
  Usage	   : URL_Get(name)
  Arguments   : name - The NAME out of NAME=VALUE
\\* ---------------------------------------------------------------------- */
function URL_Get(name) {
if (URL_Exists(name)) {
if (URL_GetLength(name) == 1) {
var theval = "";
var sections = location.search.substr(1).split("&")
for (i=0; i<sections.length; i++) {
var sectionsplit = sections[i].split("=")
if (sectionsplit[0] == name) {
theval = sectionsplit[1]
break;
}
}
return theval
}
else {
var thevals = new Array();
var sections = location.search.substr(1).split("&")
for (i=0; i<sections.length; i++) {
var sectionsplit = sections[i].split("=")
if (sectionsplit[0] == name) {
thevals[thevals.length] = sectionsplit[1]
}
}
return thevals
}
}
else {
return "ERROR";
}
}


#20

Don't you just love when a script overwrites onmouseover, ect.. events ?

Here's somthing I've been exparamenting with to help with that problem,

function doSomthingSpiffy(){
  alert("Ok, not too spiffy... but at least I showed up");
}

function todaysCoolThing(){
   if(confirm("should I fire the original event ?")){
      eval(this.onmouseover2);
   }else{
      alert("party pooper..");
   }
}

function overLoad(elm,meth,newFun){
   var oFn=elm[meth].toString().split("");
   for(var fun=false;!fun;){
     var c=oFn.shift();
     if(c==")"){
       fun=true;
     }
   }
   elm[meth+"2"]=oFn.join("");
   elm[meth]=newFun;
}
...............skipping to end, or wrapping in an onload (or overLoaded onload..)

document.links[0].onmouseover = doSomthingSpiffy;

if(!document.links[0].onmouseover){
   document.links[0].onmouseover = todaysCoolThing;
   document.links[0].onmouseover2 = false;
}else{
   overLoad(document.links[0], "onmouseover", todaysCoolThing);
}

The idea behind this is that function objects converted to strings always have a name, even the anonamous events assigned inline.

Assigning "....onmouseover="alert(this.onmouseover.toString());"..." to a link will alert "function onmouseover(event){...." in Firefox, or "function anonymous(){...." in Internet Explorer. If you split() this string(I just like arrays...) & shift() off everything up to & including the first ) found, you now have just the object {} as a string which you can stash in an "onmouseover2" attribute. Now in the event that would normally overwrite the original event you end with eval(this.onmouseover2); to call a truely anonamous function that you have stashed with the overLoad.