What Netscape failed to document was that
handler text provided for handling events within attribute
values of HTML tags is converted to a function with a special
scope chain. This scope chain comprises function local scope,
the element node to which the event handler is attached, the
current form object (if any), the document object, and finally
the global (window) object.
When you have described this previously I have though that it didn't
quite correspond with my experience, particularly the suggestion that
the internal implementation was using a - with(obj) - type statements to
selectively set-up a scope chain. On further investigation it seems that
you are correct and my perception of discrepancies arose from a
relatively wide diversity of implementations.
To test the proposition I created the following test page. It creates 10
global properties with the names 'ex0' to 'ex9' then 9 properties on the
document with the names 'ex1' to 'ex9', 8 on the body 'ex2' - 'ex9', 7
on the outer DIV element and so on progressively down the DOM until it
gets to the leaf nodes. Then various onclick handlers attempt to report
the values of the (unqualified) identifiers 'ex0' to 'ex9' to see where
the values are retrieved from (as the first value fond in the scope
chain will be the one reported).
<html>
<head>
<title></title>
<script type="text/javascript">
function setExpandos(){
setExs(window,0, 'global');
setExs(document,1, 'document');
setExOn(document.body,2, 'body');
}
function setExOn(obj, depth, data){
if(obj.nodeType == 1){
setExs(obj,depth, data);
//if(obj.onclick)obj.onclick = showExpandos;
var o = obj.children||obj.childNodes;
for(var c = 0;c < o.length;c++){
setExOn(o[c], (depth+1), (depth+1));
}
}
}
function setExs(obj,start, data){
for(var c = start;c < 10;c++){
obj['ex'+c] = data+((obj.nodeName)?(' '+obj.nodeName):'');
}
}
var res = [
'chain results > ',
'\nex0 = ','', //2
'\nex1 = ','', //4
'\nex2 = ','', //6
'\nex3 = ','', //8
'\nex4 = ','', //10
'\nex5 = ','', //12
'\nex6 = ','', //14
'\nex7 = ','', //16
'\nex8 = ','', //18
'\nex9 = ','' //20
];
function showExpandos(){
var a = res;
a[2] = ex0;
a[4] = ex1;
a[6] = ex2;
a[8] = ex3;
a[10] = ex4;
a[12] = ex5;
a[14] = ex6;
a[16] = ex7;
a[18] = ex8;
a[20] = ex9;
alert(a.join(''));
return false;
}
</script>
</head>
<body onload="setExpandos();">
<div>
<form action="">
<div>
<p>
<input type="button" value="Form Button"
onclick="var a = res;a[2] = ex0;a[4] = ex1;
a[6] = ex2;a[8] = ex3;a[10] = ex4;
a[12] = ex5;a[14] = ex6;a[16] = ex7;
a[18] = ex8;a[20] = ex9;
alert(a.join(''));return false;">
</p>
</div>
</form>
<table>
<thead>
<tr><th><a href="#"
onclick="var a = res;a[2] = ex0;a[4] = ex1;
a[6] = ex2;a[8] = ex3;a[10] = ex4;
a[12] = ex5;a[14] = ex6;a[16] = ex7;
a[18] = ex8;a[20] = ex9;
alert(a.join(''));return false;">
thead</a></th></tr>
</thead>
<tbody>
<tr><td><span>
<a href="#"
onclick="var a = res;a[2] = ex0;a[4] = ex1;
a[6] = ex2;a[8] = ex3;a[10] = ex4;
a[12] = ex5;a[14] = ex6;a[16] = ex7;
a[18] = ex8;a[20] = ex9;
alert(a.join(''));return false;">
tbody</a></span></td></tr>
</tbody>
</table>
</div>
</body>
</html>
Initially testing IE 6, Mozilla 1.3 and Opera 7.11, the three onclick
functions reported (best viewed with a fixed-width font):-
IE 6 Mozilla 1.3 Opera 7.11
button element onclick -------------------------------------
ex0 = global global global
ex1 = document #document document #document global
ex2 = document #document body BODY global
ex3 = document #document 3 DIV global
ex4 = 4 FORM 4 FORM 4 FORM
ex5 = 4 FORM 4 FORM 4 FORM
ex6 = 4 FORM 4 FORM 4 FORM
ex7 = 7 INPUT 7 INPUT 7 INPUT
ex8 = 7 INPUT 7 INPUT 7 INPUT
ex9 = 7 INPUT 7 INPUT 7 INPUT
first link onclick ----------------------------------------
ex0 = global global global
ex1 = document #document document #document global
ex2 = document #document body BODY global
ex3 = document #document 3 DIV global
ex4 = document #document 4 TABLE global
ex5 = document #document 5 THEAD global
ex6 = document #document 6 TR global
ex7 = document #document 7 TH global
ex8 = 8 A 8 A 8 A
ex9 = 8 A 8 A 8 A
second link onclick ---------------------------------------
ex0 = global global global
ex1 = document #document document #document global
ex2 = document #document body BODY global
ex3 = document #document 3 DIV global
ex4 = document #document 4 TABLE global
ex5 = document #document 5 TBODY global
ex6 = document #document 6 TR global
ex7 = document #document 7 TD global
ex8 = document #document 8 SPAN global
ex9 = 9 A 9 A 9 A
Each browser clearly is building a very specific scope chain for these
internally generated event-handling functions.
Mozilla's behaviour is interesting as for the A elements its scope chain
includes all of the element ancestors in the DOM up to the global
object, yet with the form element it has included the body and the outer
DIV but the P and DIV elements that lie between the form and the input
element have been omitted.
My /personal/ style and advice for cross browser scripting
is to avoid short cut identifiers in handler text supplied
in HTML, use the "this" object to refer to the current element
in achieving some shortcuts, and to *not* give global variables
or functions the same name as any id or name value used for
HTML elements.
I would have to agree with that 100%, especially given that even the
major browsers do not create a consistent scope chain for these
attribute-defined event handling functions.
Richard.