Event Handler Content Attributes are event handler attributes that appear in the HTML source.
When an element has an event handler content attribute, the value
of that attribute becomes the FunctionBody
of a function that the browser calls when it fires that event.
Modern browsers augment the FunctionBody
's scope chain with the element, the element's FORM
(if it is a form control), and document
. There is no official standard for this augmented scope chain.
Older browsers, such as Safari 2, Mozilla 1.x, Opera 7, differ. Scope augmentation occurs for all
event handler content attributes with the notable exception of the body
element, for
which event handler scope is not consistently augmented across event types and implementations.
The context (thisArg
) is (with the exception of body
), the element
itself. In the browsers that implement DOM Events [DOMEvents],
the event handler function has a single parameter named event
.
Given the following markup:
<p onclick="self.alert(event);"></p>
The augmented scope chain, if written in ECMAScript, would look like:
function onclick(event) { with(document) { with(this.form) { with(this) { self.alert(event); } } } }
Note that some browsers will not supply an event
parameter.
This example shows how window
and document
are shadowed:
<form action=""> <input type="hidden" name="document"> <button type="button" name="window" onclick="self.alert([window.tagName, document.tagName])">self.alert([window.tagName, document.tagName])</button> </form>
The augmented scope chain, if written in ECMAScript, would look like:
function onclick(event) { with(document) { with(this.form) { with(this) { self.alert([title, files, focus == window.focus]); var e = event||window.event; if(e && e.preventDefault) e.preventDefault(); e.returnValue = false; } } } }
For all intents and purposes, the browser's
window
property of the global
object is
an alias to the the global
object itself.
Relying on an augmented scope chain to resolve properties may
have unexpected results in different environments (i.e. browsers). The following example
shows how in at least two browsers, files
is resolved as a property
of an input
element.
<script type="text/javascript">
var files = [1,2,3];
</script>
<form action="">
<input onclick="self.alert([title, files, focus == window.focus]);
var e = event||window.event;
if(e && e.preventDefault) e.preventDefault();
e.returnValue = false;" type="file">
</form>
",[object FileList],false"Opera 9.5, IE7, IE8:
",1,2,3,false"
The identifier files
is resolved on the input element
in Firefox 3 and Safari 3. In IE8 or Opera 9.5, files
is
resolved on the window object.
A modified example from c.l.js thread "Works in ie and opera not mozilla", by Richard Cornford.
ex0 = global ex1 = document #document ex2 = document #document ex3 = document #document ex4 = 4 FORM ex5 = 4 FORM ex6 = 4 FORM ex7 = 7 INPUT ex8 = 7 INPUT ex9 = 7 INPUT // First link ex0 = global ex1 = document #document ex2 = document #document ex3 = document #document ex4 = document #document ex5 = document #document ex6 = document #document ex7 = document #document ex8 = 8 A ex9 = 8 A // Second link ex0 = global ex1 = document #document ex2 = document #document ex3 = document #document ex4 = document #document ex5 = document #document ex6 = document #document ex7 = document #document ex8 = document #document ex9 = 9 A
Most of the above results were provided by Juriy Zaytsev on thread Cross-Browser Mouse Event Handling.
Less recent browsers, including Safari 2.0.4, Mozilla 1.x, and Opera 7, featured different scope chains.
BODY
Tag.
The body
tag's event handler attributes are either mapped to
window
(which has no tag) or to the BODY
element.
Results vary based on the event and the browser. Do not use event handler
attributes for the body
element.
An augmented scope chain, combined with event handler content attributes, means that properties of the element itself, the element's form (if it is a form control), and document, may shadow properties of the window object. As explained in: select?, and hashchange only dispatched in history traversal, comments by Garrett Smith. Shortened code excerpt:
<img name='alert' alt="Alert!" src="alert.jpg"> <button onclick="self.alert(alert);">self.alert(alert);</button>
Alerts [object HTMLImageElement] (or similar implementation-dependent string).
By using an unsafe name of "alert" for an IMG
,
The window
's alert
property
identifier is shadowed by document
's alert
property identifier because
document
is in the event handler's augmented scope
before window
.
By using event handler content attributes and unsafe names,
document
and window
, the respective identifiers
are resolved on the augmented scope chain.
The augmented scope chain creates more ambiguity and increases the number of unsafe names.
FORM
,
body
, or document
. Instead, use fully qualified property lookups,
e.g. document.body
, this.form.elements
.
alert
being resolved on an object other than window
.
body
.
id
or name
attribute values.