By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,136 Members | 1,212 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,136 IT Pros & Developers. It's quick & easy.

clicking on list elements - problem

P: n/a
abs
Hi all.

My list:

<ul>
<li id="a" onclick="show(this)">Aaaaaaaa</li>
<li id="b" onclick="show(this)">Bbbbbbbb</li>
<li id="c" onclick="show(this)">Cccccccc
<ul>
<li id="d" onclick="show(this)">111111</li>
<li id="e" onclick="show(this)">222222</li>
<li id="f" onclick="show(this)">333333
<ul>
<li id="g" onclick="show(this)">@@@@@@@@@</li>
<li id="h" onclick="show(this)">{{{{{{{}</li>
<li id="i" onclick="show(this)">????>>>>></li>
</ul>
</li>
</ul>
</li>
</ul>

<ul>
<li id="j" onclick="show(this)">qqq</li>
<li id="k" onclick="show(this)">vvvv</li>
</ul>

And function:

function show(clicked)
{
alert(clicked.id)
}

The trouble is that when I click on the list element having id="g", there
appear three alerts one by one showing "g", then "f", and "c". Prabably
that's because those element are nested. How could I prevent showing the id
of clicked element and its parents ? I'd like only clicked element's id to
be showed.

Best regards,
ABS
Jul 23 '05 #1
Share this Question
Share on Google+
33 Replies


P: n/a
VK
The best trick for all this event mess so far I found is from Lasse
Reichstein Nielsen:
....
<li id="i" onclick="show(this, (event.target||event.srcElement))">Some
text*</li>
....

function show(src,trg) {
if (src == trg) {
alert(src.id);
}
}

Works for IE 6.x and FF 1.0.3/4

Jul 23 '05 #2

P: n/a
abs
> The best trick for all this event mess so far I found is from Lasse
Reichstein Nielsen: [...]


That works ! Thank you !

ABS
Jul 23 '05 #3

P: n/a
abs wrote:
Hi all.

My list:

<ul>
<li id="a" onclick="show(this)">Aaaaaaaa</li>
<li id="b" onclick="show(this)">Bbbbbbbb</li>
<li id="c" onclick="show(this)">Cccccccc
<ul>
<li id="d" onclick="show(this)">111111</li>
<li id="e" onclick="show(this)">222222</li>
<li id="f" onclick="show(this)">333333
<ul>
<li id="g" onclick="show(this)">@@@@@@@@@</li>
<li id="h" onclick="show(this)">{{{{{{{}</li>
<li id="i" onclick="show(this)">????>>>>></li>
</ul>
</li>
</ul>
</li>
</ul>

<ul>
<li id="j" onclick="show(this)">qqq</li>
<li id="k" onclick="show(this)">vvvv</li>
</ul>

And function:

function show(clicked)
{
alert(clicked.id)
}

The trouble is that when I click on the list element having id="g", there appear three alerts one by one showing "g", then "f", and "c". Prabably that's because those element are nested. How could I prevent showing the id of clicked element and its parents ? I'd like only clicked element's id to be showed.

Best regards,
ABS


Might want to consider a more global approach to handling those
clicks...

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">

li {
background: #ddd;
margin: 2px 0;
cursor: pointer;
}

</style>
<script type="text/javascript">

document.onclick = function(e)
{
var tgt;
if ((e = e || window.event)
&& (tgt = e.srcElement || e.target)
&& /LI/i.test(tgt.nodeName))
{
alert(tgt.id);
}
}

</script>
</head>
<body>
<ul>
<li id="a">Aaaaaaaa</li>
<li id="b">Bbbbbbbb</li>
<li id="c">Cccccccc
<ul>
<li id="d">111111</li>
<li id="e">222222</li>
<li id="f">333333
<ul>
<li id="g">@@@@@@@@@</li>
<li id="h">{{{{{{{}</li>
<li id="i">????>>>>></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li id="j">qqq</li>
<li id="k">vvvv</li>
</ul>
</body>
</html>

Jul 23 '05 #4

P: n/a
abs
abs wrote:
That works ! Thank you !


But there'e one problem. When I add onclick to element like this:

liElement.onclick = function(){show(this, (event.target||event.srcElement))}

If then I click the element, Firefox claims: "Error: event is not defined".
But when I define onclick inline, like here

<li id="i" onclick="show(this,
(event.target||event.srcElement))">Sometext*</li>

everything's fine with click and works. So, what's the difference and
where's the problem ?

ABS
Jul 23 '05 #5

P: n/a
abs
RobB wrote:
Might want to consider a more global approach to handling those
clicks... [...]


Thank you. That helped a lot.

Regards,
ABS
Jul 23 '05 #6

P: n/a
abs wrote:
abs wrote:
That works ! Thank you !
But there'e one problem. When I add onclick to element like this:

liElement.onclick = function(){show(this,

(event.target||event.srcElement))}
If then I click the element, Firefox claims: "Error: event is not defined". But when I define onclick inline, like here

<li id="i" onclick="show(this,
(event.target||event.srcElement))">Sometext*</li>

everything's fine with click and works. So, what's the difference and
where's the problem ?

ABS


Glad to hear it. Try...

liElement.onclick = function(e){show(this, (e.target||e.srcElement))}

When you register a handler programmatically (JS) the mozilla Event
object is automatically passed to your handler as arguments[0]. You
need to catch it at the other end, even if the handler is a wrapper (as
above). Handlers assigned in HTML are wrapped automatically and the
Event object is exposed as the local variable 'event'.

Jul 23 '05 #7

P: n/a
Oops, cross-browser...

liElement.onclick = function(e)
{
if (!e) e = window.event;
show(this, (e.target||e.srcElement))
}

Jul 23 '05 #8

P: n/a

P: n/a
abs wrote:
But there'e one problem. [...]

liElement.onclick = function(){show(this,
(event.target||event.srcElement))}


The IE event model differs from that used by most user agents, and the one
defined by the W3C. IE uses a global object called event to communicate
event-related information, whereas the W3C/Netscape model passes the event
object to listeners as an argument.

When a user agent encounters an intrinsic event in markup, it creates an
anonymous function that contains the code. Here, again, we find
differences.

When parsing

<element on<type>="/* User code */">

IE produces an intrinsic event listener like:

element.on<type> = function() {
/* User code */
};

This is fine because the event object is global in IE (and any user agents
that choose to follow it), so it can still be accessed. However, user
agents that follow the Netscape/W3C event model internally produce
intrinsic event listeners like:

element.on<type> = function(event) {
/* User code */
};

That is, they pass a reference to the event object with the identifier,
'event', to listeners. In your code, you don't try to access this argument,
so Firefox and others will not find an event object.

Change your code to:

liElement.onclick = function(e) {
e = e || event; /* Use either the argument, if supplied,
* or the global object.
*/
show(this, e.target || e.srcElement);
};

[snip]

There is one potential problem: your code will only work if the target
element is what you expect. If you have any other elements within the list
item, the target is likely to be one of those elements. Just keep that in
mind.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #10

P: n/a
VK
Here the better variant I have by now. I coming to the conclusion that
it's better don't use intristic event handlers in NN/FF, they are too
unstable.
It gives your more code in the <script> section, but you keep your <ul>
lists nice and clean. W3 should be happy: scripting, styling and
content are all separate and independent :-)

<html>
<head>
<title>UL's</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<script>
var isDOM = window.addEventListener;

function init() {
var foo = null;
var tmp = document.getElementsByTagName('LI');
for (i=0;i<tmp.length;i++) {
/* Add EventListener on the capturing phase
so we don't have to bother with bubbles history */
foo = (isDOM)?
tmp[i].addEventListener('click',test,true) :
tmp[i].attachEvent('onclick',test);
}
}

function test(e) {
var tmp = '';
if (isDOM) {
e.stopPropagation();
tmp = e.target.innerHTML;
}
else {
event.cancelBubble = true;
tmp = event.srcElement.innerHTML;
}
alert(tmp);
}

window.onload = init;
</script>
</head>

<body bgcolor="#FFFFFF">
<ul>
<li>Level 1 - Item 1</li>
<li>Level 1 - Item 2
<ul>
<li>Level 2 - Item 1</li>
<li>Level 2 - Item 2
<ul>
<li>Level 3 - Item 1</li>
<li>Level 3 - Item 2</li>
<li>Level 3 - Item 3</li>
</ul>
</li>
<li>Level 2 - Item 3</li>
</ul>
</li>
<li>Level 1 - Item 3</li>
</ul>
</body>
</html>

Jul 23 '05 #11

P: n/a
VK wrote:
Here the better variant I have by now. I coming to the conclusion that
it's better don't use intristic event handlers in NN/FF, they are too
unstable.
You have complained a number of times in recent posts about 'NN/FF',
but generally your discoveries have only shown the variances between IE
and Mozilla event models. That does not make Mozilla-based browsers
'unstable', it just means you have to take account of both event
models in your code.

Does adding an event handler dynamically avoid intrinsic events, or is
it just a different way of adding them?
It gives your more code in the <script> section, but you keep your <ul>
lists nice and clean. W3 should be happy: scripting, styling and
content are all separate and independent :-)

<html>
<head>
<title>UL's</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<script>
var isDOM = window.addEventListener;

function init() {
var foo = null;
var tmp = document.getElementsByTagName('LI');
for (i=0;i<tmp.length;i++) {
/* Add EventListener on the capturing phase
so we don't have to bother with bubbles history */
foo = (isDOM)?
tmp[i].addEventListener('click',test,true) :
tmp[i].attachEvent('onclick',test);
}
}

function test(e) {
var tmp = '';
if (isDOM) {
e.stopPropagation();
tmp = e.target.innerHTML;
}
else {
event.cancelBubble = true;
tmp = event.srcElement.innerHTML;
}
alert(tmp);
}

window.onload = init;
</script>


To support older browsers, the following may suit:

function show(x) {
alert( (x.id || 'No id') + '\n' + x.innerHTML);
}
function init(){

if (document.getElementsByTagName){
var lis = document.getElementsByTagName('LI');
} else if (document.all){
var lis = document.all.tags('LI');
} else {
return;
}

var i=lis.length;
while (i--){
lis[i].onclick = function(e) {
e = e || window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
show(this);
}
}
}

--
Rob
Jul 23 '05 #12

P: n/a
VK
> Does adding an event handler dynamically
avoid intrinsic events, or is it just a different way of adding them?


Using intrinsic events forces you to use the non-documented EVENT
object in FF (Some people tried to say here that this is some special
EVENT and it has nothing to do by its nature with window.event in IE).

<html>
<head>
<title>Event</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
</head>
<body>
<p onclick="alert(event.target)">Test</p>
</body>
</html>

Click and get it. I did not create this EVENT object, nevertheless it's
available and self-updating. Thus it's a global public self-updating
event object. Thus it's equal to windows.event in IE. (By trying to
find some contextual differences we would have some religious
discussion here, sort of is Mary holy or is she just God's mother). But
Mozilla is dead silent about this object. They don't promise us any
properties or behaviours. So better use dynamic handlers. They are much
more flexible and in case if something doesn't work, we can always say
"hey, look what did you say and what do we have!".

Jul 23 '05 #13

P: n/a
"RobB" <fe******@hotmail.com>, haber iletisinde sunlari
yazdi:11**********************@g14g2000cwa.googleg roups.com...
Leisure reading: #;=)

http://www.onlinetools.org/articles/...ipt/index.html


could you please explain this line (or point to some online source that
could help me understand):

if ((e = e || window.event)
&& (tgt = e.srcElement || e.target)
&& /LI/i.test(tgt.nodeName))

i sometimes come across with such beautiful techniques suggested by js
masters but none of the books i have includes them.
Jul 23 '05 #14

P: n/a
VK wrote:
Using intrinsic events forces you to use the non-documented EVENT
object in FF
Whilst I've never seen explicit documentation (more implication than
anything else), both Netscape's JavaScript Guide and Mozilla's DOM
Reference contain an example (different in each case) that uses the 'event'
identifier in the context of an intrinsic event attribute. In addition,
showing the string representation of an intrinsic event property clearly
reveals the presence of an argument named 'event'.

This behaviour is used by every scriptable user agent that follows the
Netscape event model that I've ever encountered. To dismiss overwhelming
empirical evidence just because Netscape didn't bother to state the
behaviour explicitly is quite ridiculous.
(Some people tried to say here that this is some special EVENT and it
has nothing to do by its nature with window.event in IE).
They are common in that they both provide access to event-related
information. How they are provided is very different.

[snip]
<p onclick="alert(event.target)">Test</p>
[snip]
Click and get it. I did not create this EVENT object [...]
No, the user agent did. When the attribute is encountered, it is converted
into an anonymous function internally. Using the Netscape event model, this
is exactly equivalent to:

pElement.onclick = function(event) {
alert(event.target)
};

You can see this representation (excluding the assignment itself) by showing
the toString value, as I stated above.

<p onclick="alert(this.onclick);">Test</p>

will display:

function(event) {
alert(this.onclick);
}

Why is this so difficult to comprehend?
Thus it's a global public self-updating event object.


That's a leap which you cannot support. If true, one could write:

function myListener() {
alert(event.target);
}

<p onclick="myListener();">Test</p>

and still examine the event object, but you can't outside the IE event
model. The identifier is a formal argument of a function object created by
the user agent. It is not a global.

[snipped nonsense]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #15

P: n/a
Andy LW wrote:

[snip]
could you please explain this line (or point to some online source that
could help me understand [an if statement]
Essentially, the expression gets a reference to the event target, and checks
that this target is a list item (LI) element. I'll walk through it in
detail.

document.onclick = function(e) {
var tgt;
if ((e = e || window.event)
If you've managed to wade through the silliness, you will hopefully have
grasped that there are basically two event models: Netscape and IE.

The Netscape model passes the event object to a listener as an argument,
whilst IE provides a global object. So, the first thing we need to do is
get this object in one place. The expression

(e = e || window.event)

is fairly simple. The logical OR operator evaluates its operands as
booleans. If the first operand evaluates to true, the /value/ of that
operand will be the result. If the first operand evaluates to false, the
value of the second operand will be the result. In other words, if e is not
an object reference, replace its value with that of window.event.
&&
Before moving on to the next expression, we need to make sure that e
actually contains an event object. To do this, we use the logical AND
operator to ensure that all of the expressions in the if statement evaluate
to true.
(tgt = e.srcElement || e.target)
As part of the difference in event models, both use a different property to
refer to the target of an event. The Netscape/W3C model uses target, whilst
IE uses srcElement. The tgt variable will be assigned one of these
values...
&& /LI/i.test(tgt.nodeName))


Finally, this regular expression checks the nodeName property of the event
target. The nodeName property contains the tag name for elements (and other
values for other node types). We want to ensure that the event was
targeting a list item (LI), so the expression makes sure that the node name
contains this value.

The regular expression contains the i (case-insensitive) flag. The reason
for this is that the nodeName value can vary depending on whether a
document is HTML or XHTML. With HTML (and XHTML served as HTML), a tag name
(like LI) is always uppercase, and values for other node types (like #text)
are lowercase. With XML-based documents (namely XHTML), the nodeName value
uses the case of the element as XML, unlike SGML, is case-sensitive. This
means that elements borrowed from HTML (like P, TABLE, etc.) are always
lowercase, elements defined in other namespaces may vary. Using a
case-insensitive comparison sidesteps all of this.

I hope that made sense.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #16

P: n/a
VK wrote:
Does adding an event handler dynamically
avoid intrinsic events, or is it just a different way of adding them?

Using intrinsic events forces you to use the non-documented EVENT
object in FF (Some people tried to say here that this is some special
EVENT and it has nothing to do by its nature with window.event in IE).


Not documented? A quick search of the Mozilla site yielded:

<URL:http://devedge-temp.mozilla.org/library/manuals/2000/javascript/1.3/guide/evnt.html>

<URL:http://www.mozilla.org/docs/dom/domref/examples.html#999002>

<URL:http://www.mozilla.org/docs/dom/domref/examples8.html>

<URL:http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event>

You have yet to show any evidence that coding events inline is more
'unstable' than adding them dynamically. Adding events dynamically is
more aligned with 'best practice', but that is not the point. Adding
events inline does not 'force' you to use the event object, nor is it
'unstable'.

The difference is that with IE the event object is global, with Mozilla
it is local and therefore you have to access it differently - for the
vast majority of scripts, you don't need to bother with it at all.

<html>
<head>
<title>Event</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
</head>
<body>
<p onclick="alert(event.target)">Test</p>
</body>
</html>

Click and get it. I did not create this EVENT object, nevertheless it's
Have a look at the properties of an HTML element's style object. You
didn't 'create' them, yet they are there. They are accessible on every
element, but they aren't global.

<p id="x">This is a paragraph</p>
<p id="y"></p>
<script type="text/javascript">
var x = document.getElementById('x');
var z = [];
for (prop in x.style){
z.push( prop + ': ' + ( x.style[prop] || '&nbsp;<i>not set</i>' ) );
}
document.getElementById('y').innerHTML = z.join('<br>');
</script>

available and self-updating. Thus it's a global public self-updating
event object.
No, in the Mozilla model it's a local object belonging to each event.
Thus it's equal to windows.event in IE.


In my mind it's equivalent to, not equal to.

[...]

--
RobG
Jul 23 '05 #17

P: n/a
VK
> Not documented? A quick search of the Mozilla site yielded:
<URL:http://devedge-temp.mozilla.or*g/library/manuals/2000/javascr*ipt/1.3/g...>
<URL:http://www.mozilla.org/docs/do*m/domref/examples.html#999002>
<URL:http://www.mozilla.org/docs/do*m/domref/examples8.html>

<URL:http://www.w3.org/TR/DOM-Level*-2-Events/events.html#Events-E*vent>

Did you actually read these docs or just checked for presence of the
word "Event"? We are not talking about "Event" as a conceptual
definition, we are talking about THAT event, which is in <...
onclick="alert(event.target)">
Taking this into account, read these docs once again. And don't forget
the main one:
<http://www.mozilla.org/docs/dom/domref/dom_event_ref.html#998197>

If you find anything about THAT event, send me your PanPal acc#, I owe
you 10 bucks.

Jul 23 '05 #18

P: n/a
VK
>> Thus it's a global public self-updating event object.
That's a leap which you cannot support.
Actually I can ;-) This object is just a little bit under-done, and for
more confusion is hidden under a bunch of university terms.
Try this in FF:
....
function test() {
var obj = document.getElementById('p1');
alert(obj.onclick.arguments[0].currentTarget.innerHTML);
}
....
<p id="p1" onclick="test2()">Click me</p>
....

All they had to do: make an anonymous forwarding of event reference (as
arguments[0]) to the event handler. They already did it for the event
capturer, so having said "A" say "B" also. So we would not need to use
this sidewalk, and we would have a full equivalent of IE scheme. OK,
methods are called differently, but we are living with it since the
beginning of times.
Why is this so difficult to comprehend?

It IS difficult to comprehend: the 'event' you can learn only from the
street, the "Russian hills rider" from the official docs, and a bunch
of details which are not covered or covered wrongfully. I'm maybe not
the smartest one here, but still BS in linguistics... It took nearly 5
days of intensive reading and posting to get the picture clear.

Jul 23 '05 #19

P: n/a
On 20/05/2005 18:11, VK wrote:
Thus it's a global public self-updating event object.
That's a leap which you cannot support.


Actually I can ;-)


No, you can't (and haven't). In the Netscape/W3C model, the event object
is local, not local. It could be a single object that is altered when
passed between elements, but it doesn't have to be, so 'self-updating'
doesn't necessarily apply, either. As for 'public', I'm not quite sure
what you're trying to imply. It's as public as any local variable can be.

[snip]
function test() {
var obj = document.getElementById('p1');
alert(obj.onclick.arguments[0].currentTarget.innerHTML);
}
...
<p id="p1" onclick="test2()">Click me</p>


What do you think that proves, aside from the fact that deprecated usage
of the arguments object is still supported? The behaviour has nothing to
do with the involvement of the event object:

function a() {
b();
}
function b() {
alert(a.arguments[0]);
}

a('some value');

You're simply accessing the arguments object as a property of some
function within the execution context stack - a feature which is not
specified in ECMA-262 3rd Ed.

[snip]
Why is this so difficult to comprehend?


It IS difficult to comprehend: the 'event' you can learn only from the
street [...]


There will have been examples and articles produced for the past decade,
or so, which demonstrate the usage that's been described. It's been
around from at least NN4; possibly earlier. I agree that it should have
been included in some 'official' documentation, but it hasn't. If you're
that concerned, talk to the Mozilla documentation team and get them to
describe it in their Web Developer section.

[snip]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #20

P: n/a
"Michael Winter" <m.******@blueyonder.co.invalid> wrote in message
news:52*****************@text.news.blueyonder.co.u k...
Andy LW wrote:

[snip]
could you please explain this line (or point to some online source that
could help me understand [an if statement]


Essentially, the expression gets a reference to the event target, and
checks
that this target is a list item (LI) element. I'll walk through it in
detail.

document.onclick = function(e) {
var tgt;
if ((e = e || window.event)


If you've managed to wade through the silliness, you will hopefully have
grasped that there are basically two event models: Netscape and IE.

The Netscape model passes the event object to a listener as an argument,
whilst IE provides a global object. So, the first thing we need to do is
get this object in one place. The expression

(e = e || window.event)

is fairly simple. The logical OR operator evaluates its operands as
booleans. If the first operand evaluates to true, the /value/ of that
operand will be the result. If the first operand evaluates to false, the
value of the second operand will be the result. In other words, if e is
not
an object reference, replace its value with that of window.event.
&&


Before moving on to the next expression, we need to make sure that e
actually contains an event object. To do this, we use the logical AND
operator to ensure that all of the expressions in the if statement
evaluate
to true.
(tgt = e.srcElement || e.target)


As part of the difference in event models, both use a different property
to
refer to the target of an event. The Netscape/W3C model uses target,
whilst
IE uses srcElement. The tgt variable will be assigned one of these
values...
&& /LI/i.test(tgt.nodeName))


Finally, this regular expression checks the nodeName property of the event
target. The nodeName property contains the tag name for elements (and
other
values for other node types). We want to ensure that the event was
targeting a list item (LI), so the expression makes sure that the node
name
contains this value.

The regular expression contains the i (case-insensitive) flag. The reason
for this is that the nodeName value can vary depending on whether a
document is HTML or XHTML. With HTML (and XHTML served as HTML), a tag
name
(like LI) is always uppercase, and values for other node types (like
#text)
are lowercase. With XML-based documents (namely XHTML), the nodeName value
uses the case of the element as XML, unlike SGML, is case-sensitive. This
means that elements borrowed from HTML (like P, TABLE, etc.) are always
lowercase, elements defined in other namespaces may vary. Using a
case-insensitive comparison sidesteps all of this.

I hope that made sense.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.

thank you very, very much for your patience and detailed explanations. that
was much more than i expected to get. you left nothing unexplained and
unclear. thank you again.
Jul 23 '05 #21

P: n/a
VK
If anyone is still watching this thread:
A week ago I took a small tech-writing gig for a DLL library. That put
me "face down" to the background life of all this stuff.

I have to admit that my "public self-updating event object" is
total bs (and unlike the science degree, this "bs" is all in small
letters and staying from other famous words :-(

Michael Winter tried to explain this to me, but I did not get it.

There is no "public self-updating event object" neither in IE, nor
in FF, nor in any other browser.
There is unique Event object, that acts almost exactly like the Date
object.
The Date object is always "ticking" counting milliseconds. If we do
new Date(), the Date object creates a copy of itself with the
"timestamp" of the moment of the creation. We receive a reference
on this copy for further work. Evidently the original and the copy are
equal to each other, but just one millisecond later they are not (the
Date keeps ticking, the timestamp is frozen).

The Event object is continuously changing, passing through itself all
incoming events. At the moment of any event it checks for registered
event listeners of this particular event type. If there is at least
one, then the Event creates a momentary copy of itself, we could call
it "eventstamp". This "eventstamp" is being delivered to each
listener in some predefined order. There only 3 differences between IE
and FF:

1. Event delivery goes down->up in IE and up->down->up in FF (double
pass).

2. In IE eventstamp appears as automatically created variable
"event" in the body of the function.
In FF eventstamp appears as the first argument of the function, also in
intrinsic functions this argument as always called "event". In
regular functions you can call it however you want.

3. In IE the "event" variable is created automatically for the
outer function as well as for all inner functions. In FF you have to
save needed event properties right away, or access them in indirect way
like outerFunction.arguments[0].someEventProperty.

How does it really work - just in case if you are still curious (I
was). On the source code level there is a Message Dispatcher. It
receives messages (events) from the OS and forms the messages queue.
From that queue it takes the oldest one and goes to the special table,

where the program keeps all registered message receivers. Program sends
messages to these receivers one-by-one in the predefined order, based
on some receivers properties.

Jul 23 '05 #22

P: n/a
"VK" <sc**********@yahoo.com> writes:
There is no "public self-updating event object" neither in IE, nor
in FF, nor in any other browser.
Indeed. If you check what happens in IE, there is a global "event"
variable. Its content changes when new events are triggered, meaning
it is a new event object each time.
There is unique Event object, that acts almost exactly like the Date
object.
There is no global variable called "Event" in IE, although I believe
there is in Gecko-based browsers. There it can be used as a constructor
function for event objects ... something like Date for date objects, yes.
The Date object is always "ticking" counting milliseconds. If we do
new Date(), the Date object creates a copy of itself with the
"timestamp" of the moment of the creation.
Uhm, no.
The Date object is a single function object. It does nothing by itself.

When you create a new object based on the Date function, the new
object inherits methods from Date.prototype. It is also assigned a
value that is the current time, as reported by the operating system
(the Date function is a host object, so it can access non-Javascript
resources).
We receive a reference on this copy for further work. Evidently the
original and the copy are equal to each other, but just one
millisecond later they are not (the Date keeps ticking, the
timestamp is frozen).
No, they are even different types.

The date object created is an object. The Date function is (duh :) a
function. Test it:
alert([typeof Date, typeof new Date()]);

The Date function os more like a template, while the date object is a
real object created from the mold of the template. They are no more
equal than a cooike and a cookie cutter.
The Event object is continuously changing, passing through itself all
incoming events. At the moment of any event it checks for registered
event listeners of this particular event type. If there is at least
one, then the Event creates a momentary copy of itself, we could call
it "eventstamp". This "eventstamp" is being delivered to each
listener in some predefined order.
More likely: the browser is internally listening for input events from
the operating system. When applicable, it converts those events to DOM
events (an OS mouse click to a DOM "click" event). The browser creates
new DOM event objects as needed.
There only 3 differences between IE
and FF:

1. Event delivery goes down->up in IE and up->down->up in FF (double
pass).
Sounds correct. The Gecko engine uses the W3C DOM 2 Events model. IE
uses their own "bubbling" model (which predates DOM 2, so they were
probably an inspiration to DOM 2 Events).
2. In IE eventstamp appears as automatically created variable
"event" in the body of the function.
No. The current event is assigned to a global variable called "event"
before bubbling starts. The variable is not local to the body of the
function.
In FF eventstamp appears as the first argument of the function, also in
intrinsic functions this argument as always called "event". In
regular functions you can call it however you want.
Correct (where "intrinsic functions" are the JS functions created by
the browser from the HTML intrinsic event handler attributes).
3. In IE the "event" variable is created automatically for the
outer function as well as for all inner functions.
It's a global variable, so it's visible everywhere, except when
shadowed by a local variable with the same name.
In FF you have to
save needed event properties right away, or access them in indirect way
like outerFunction.arguments[0].someEventProperty.
Not a recommende way of accessing parameters of a function. It doesn't
work well with recursive functions, and it's not part of the ECMAScript
standard.
How does it really work - just in case if you are still curious (I
was). On the source code level there is a Message Dispatcher. It
receives messages (events) from the OS and forms the messages queue.
Agree.
From that queue it takes the oldest one and goes to the special table,
where the program keeps all registered message receivers. Program sends
messages to these receivers one-by-one in the predefined order, based
on some receivers properties.


Vague, so probably correct :)

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #23

P: n/a
VK
> There is no global variable called "Event" in IE, although I believe
there is in Gecko-based browsers.

Should we say "There is an event dispatcher in all browsers that..."
This way we are escaping a confusion between the Event as a programming
term definition (like Function, Subroutine, Loop etc) and some real
entity.
The current event is assigned to a global variable called "event"

before bubbling starts.

Don't agree. It is rather simple to recreate a situation when we are
handling several events at once (say drag and mousemove). It would mean
that we have 2 global vars with the same name and different values
(nonsense). Actually Microsoft says the same on their usual baby-talk:
"The event object is available only during an event-that is, you can
use it in event handlers but not in other code".
<http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/objects/obj_event.asp>
So the eventstamp "event" acts as private variable: generic to the
event handler and its inner functions.

outerFunction.arguments[0].som*eEventProperty.

Not a recommende way


Just thinking off a way to work with intrinsic event handler having
some arguments to pass to other function:

<div onclick="f1(arg0,arg1,arg3)"> - no problem with IE, but in FF arg0
must be sacrificed to event/event property. It is not very convenient
to reserve first argument in each function for e, just in case if it
will be called from an intrinsic event handler.
?

Jul 23 '05 #24

P: n/a
window.event always exists in IE, though outside of an event handler
(or recursively-called functions) its value is reported as null. It
doesn't seem possible to retrieve a reference to the window.event
object -- it always gives back a copy of itself (see code segment
below).

Based on this and several other quick-and-dirty experiments, it seems
most likely that IE has an internal class it uses to represent an
event, which it instantiates and exposes as window.event. When the
event's registered handler finishes, the value of window.event is
reverted to null (rather than a pointer or reference to an internal IE
object). The actual object is destroyed per normal garbage collection:
when its internal reference counter reaches 0.

It is also possible that it's not exposing an internal object but
instantiating a JavaScript object, but I doubt it-- trying to set
..srcElement to a string yields 'type mismatch', and error we're not
very used to seeing in JS.

Because of the garbage collection, it is possible to have two 'Event
objects' instantiated (by keeping at least one reference to an event
that was already processed), but I'm not certain that there is a way to
make two events _fire_ simultaneously. I've never tried on a
dual-processor machine. I did attempt in a very cursory fashion to make
IE process two events simultaneously, but it wouldn't do it. It wanted
to handle each sequentially.
It would mean that we have 2 global vars with the same name and
different values (nonsense).
Not necessarily.

An onClick for a submit button is processed in its entirety before IE
'bubbles' upward, instantiating a new Event object and referencing it
with window.event then calling the form's onClick. When the form's
onClick return()s, IE 'bubbles' again, instantiating a new Event
object, to the body. When bubbling has finished, it instantiates an
Event and calls the form's registered onSubmit handler.

In fact, I couldn't get IE to run any other code while a handler was
running, so I couldn't get a better look at some of the finer details
in question here.

Point being, only one value for window.event is ever required at any
given moment.
Code segment referenced above:
<html>
<script>

var x = window.event;
var y;

function onload() {
y = window.event;
alert( x );
setTimeout( 'alert(y)', 1000 );
setTimeout( 'alert(x)', 2000 );
setTimeout( 'alert(window.event == y)', 3000 );
}

</script>
<body onload=onload() />
</html>
VK wrote:
There is no global variable called "Event" in IE, although I believe there is in Gecko-based browsers.

Should we say "There is an event dispatcher in all browsers that..."
This way we are escaping a confusion between the Event as a programming term definition (like Function, Subroutine, Loop etc) and some real
entity.
The current event is assigned to a global variable called "event" before bubbling starts.

Don't agree. It is rather simple to recreate a situation when we are
handling several events at once (say drag and mousemove). It would

mean that we have 2 global vars with the same name and different values
(nonsense). Actually Microsoft says the same on their usual baby-talk: "The event object is available only during an event-that is, you can
use it in event handlers but not in other code".
<http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/objects/obj_event.asp> So the eventstamp "event" acts as private variable: generic to the
event handler and its inner functions.

outerFunction.arguments[0].som*eEventProperty. Not a recommende way


Just thinking off a way to work with intrinsic event handler having
some arguments to pass to other function:

<div onclick="f1(arg0,arg1,arg3)"> - no problem with IE, but in FF

arg0 must be sacrificed to event/event property. It is not very convenient
to reserve first argument in each function for e, just in case if it
will be called from an intrinsic event handler.
?


Jul 23 '05 #25

P: n/a
On 24/05/2005 08:57, VK wrote:

[snip]
The current event is assigned to a global variable called "event"
before bubbling starts.
Don't agree. It is rather simple to recreate a situation when we are
handling several events at once (say drag and mousemove).


Though reentrancy may occur, events are handled synchonously. As far as
a script is concerned, there is only one event to deal with at a time.
What occurs within the application is of no consequence to us.

[snip]
"The event object is available only during an event-that is, you can
use it in event handlers but not in other code". [...]
Microsoft mean that an event object doesn't persist once it has finished
bubbling through the document.
So the eventstamp "event" acts as private variable: generic to the
event handler and its inner functions.
It has nothing to do with inner functions. In IE, the event object is
global. It's as simple as that. However, the object is transient, not
persistent.

[snip]
<div onclick="f1(arg0,arg1,arg3)"> - no problem with IE, but in FF arg0
must be sacrificed to event/event property.


Utter nonsense. Read how an intrinsic event listener is defined
internally, again. I've already demonstrated it twice in this thread.
I'm not doing it a third time.

[snip]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #26

P: n/a
JRS: In article <7j**********@hotpop.com>, dated Mon, 23 May 2005
17:46:01, seen in news:comp.lang.javascript, Lasse Reichstein Nielsen
<lr*@hotpop.com> posted :
When you create a new object based on the Date function, the new
object inherits methods from Date.prototype. It is also assigned a
value that is the current time, as reported by the operating system
(the Date function is a host object, so it can access non-Javascript
resources).

The latter only, however, if it is given no parameter.

If it is given a numeric parameter, its initialisation should be, and
IIRC on my system is, much faster, since it does not have to ask for the
time.

If it is given a string parameter, it has to work out what the parameter
means - and of course may get an answer other than the intended one (for
example, if the intended year was low-numbered).

--
John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4
<URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
Jul 23 '05 #27

P: n/a
"VK" <sc**********@yahoo.com> writes:
Should we say "There is an event dispatcher in all browsers that..."
It's true, so let's :)
The current event is assigned to a global variable called "event"
before bubbling starts.


Don't agree. It is rather simple to recreate a situation when we are
handling several events at once (say drag and mousemove).


Nope. JScript is not multithreaded, and each event his handled
completely before the next is fired. You might trigger two events at
one time, but the JScript system fires the one at a time.
It would mean that we have 2 global vars with the same name and
different values (nonsense).
Same variable, different time.
Actually Microsoft says the same on
their usual baby-talk: "The event object is available only during an
event-that is, you can use it in event handlers but not in other
code".
Which is correct, since even if you can store a reference to the event
inside the event handler code, then using it later gives the values of the
new event, not the old one.
So the eventstamp "event" acts as private variable: generic to the
event handler and its inner functions.
The name "private variable" has a quite different meaning. The "event"
variable is global. Its value is constrained to making sense only
during event handling.
<div onclick="f1(arg0,arg1,arg3)"> - no problem with IE, but in FF arg0
must be sacrificed to event/event property. It is not very convenient
to reserve first argument in each function for e, just in case if it
will be called from an intrinsic event handler.


If the function can be called both during event handling and not, then
it doesn't use the event, and there is no need to pass it as an
parameter.

If the function uses the event, then it should be called during event
handling, and I see no problem with passing it as a parameter. In fact,
I prefer the event as a paramter to using a global variable.

So, I can't see a problem here.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #28

P: n/a
On 24/05/2005 08:57, VK wrote:
<div onclick="f1(arg0,arg1,arg3)"> - no problem with IE, but in FF arg0
must be sacrificed to event/event property.


As I said very gruffly previously (I apologise), this isn't true. For
simplicity, I'll refer to the IE and Netscape event models. This isn't
accurate as other user agents also implement these models; Opera, for
instance, implements both.

When a listener is attached directly to an element, its first argument,
under the Netscape model, will receive the event object. That is, if a
listener is added using the addEventListener method, or if a reference
to a function object is assigned to an on<type> event property, then
that listener will only be called with one argument: the event object.

Code that is added via HTML attributes is different. It becomes the
function body of a listener created by the user agent itself. As such,
there are no constraints; you can do whatever you want with it. Do you
see the difference?

<div onclick="/* some code */">

and

<div id="myDiv">

document.getElementById('myDiv').onclick = function(event) {
/* some code */
};

are identical from a practical point of view. If you display the value
of the onclick property in both cases in a user agent that follows the
Netscape model, you will see the same string value.

If you wanted to call a function from within these listeners to do the
real event handling, you don't have to pass the event object first. You
are free to define the code within these listeners as you please.

<div onclick="myFunction(event, this);">

and

<div onclick="myFunction(this, event);">

are both fine. The event identifier provided by a user agent won't
suddenly stop working if you use the latter.

The difference that does exist between the listener created by the user
agent when it parsed intrinsic event attribute, and those listeners that
you add directly yourself, is that the user agent always provides the
event object through the identifier, 'event'.

<div onclick="/* You must use 'event' here to access the object. */">

This is true under either event model.

When you add the listener yourself, you can use any identifier you like
under the Netscape model.

<div id="myDiv">

document.getElementById('myDiv').onclick = function( whatever ) {
/* You now use 'whatever', here. */
};

Under the IE model, you must still use 'event':

document.getElementById('myDiv').onclick = function() {
/* No argument is passed to this listener.
* You must use the global, 'event', instead.
*/
};

So, combining them, you get:

document.getElementById('myDiv').onclick = function( whatever ) {
whatever = whatever || event;
};
Unless you state what you don't understand about this, I doubt anyone
will be able to help you. I think you might be trying to over analyse it
all. Your theories as to what occurs within the application, for
example, are irrelevant. It has no effect on how you need to write event
handling code.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #29

P: n/a
VK
1. About the nature of the event object in IE:
IE creates new public event object for each event. This object is
called "event" and it is available until anyone is using it. So it can
be any amount of event objects (up to the capacity of your program
stack). All these objects are equally named "event". Only one event
object is visible to the program context at the given time. Which one -
it depends on who is the original caller (aka original event owner).
Overall it's a re-incarnation of the application message queue.

Testcase (IE only of course):

<html>
<head>
<title>Event test 009</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<script>

function test1() {
document.getElementById('p2').fireEvent('onmouseup ');
alert(test2());
}

function test2() {
return event.srcElement.innerText;
}

function test3() {
alert(event.type);
}
</script>
</head>

<body bgcolor="#FFFFFF">
<p id="p1" onclick="test1()">Line One</p>
<p id="p2" onmouseup="test3()">Line Two</p>
</body>
</html>

Click on Line One, get the event type for Line Two, get the original
event info for Line One after that.

Besides theoretical blah-blah, it answers the question about
time-consuming operations (like db connections) on events. Nothing
terrible will happen as you can see: the system will keep bubbling, but
the instance of the original event will wait you however long you want
(until the end of the session).
2. Event handling
Dear Michael, I know very well how to get event properties in a FF/IE
compatible way. Still thank you for your long responce.
The question was & is: what is the most universal and reliable way if
we need the bubbles back-tracking?
Consider the code below (instead of div's could be table cells, span's,
ul's - just search this newsgroup for samples). So we have some
universal update(objectRef, newContent) function and we want to use it
on OuterLayer, and only on it (filtering out the underlaying elements).
What update() function should we use?

[1]
...."OuterLayer" onclick="update(this,newContent)"...
....
function update(obj, content) {
// Doesn't work at all within ECMA:
// var trg = (event)? event.srcElement : /* what to do with FF? */
//if (obj == trg) {
// obj.innerHTML = content + obj.innerHTML;
//}
}

[2]
...."OuterLayer" onclick="update(this,newContent)"...
....
function update(obj, content) {
/* It works, but ECMA doesn't promise (but neither prohibits) this
functionality: */
var trg = (event)? event.srcElement : obj.onclick.arguments[0].target;
if (obj == trg) {
obj.innerHTML = content + obj.innerHTML;
}
}

[3]
....OuterLayer onclick="update(event.target, this, newContent)"...
....
function update(tar, obj, content) {
/* It works, it's ECMA-obeyant, but the first argument is reserved for
POSSIBLE argument */
var trg = (tar)? tar : event.srcElement;
if (obj == trg) {
obj.innerHTML = content + obj.innerHTML;
}
}

If I'm writing a library for further distribution, I need to take a
decision right here. My update() function can be called from anywhere:
from an event handler, from another function, directly. What is the way
to make it maximum usage-friendly?

<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<script>

</script>
<body bgcolor="#FFFFFF">
<div id="OuterLayer" onclick="<!-- do what ? -->"
style="position:absolute; width:400px; height:400px;
background-color:#FFFF99; z-index:1; left: 50px; top: 50px">
<div id="InnerLayer1" style="position:absolute; width:300px;
height:300px; background-color:#66FF66; z-index:2; left: 50px; top:
50px">
<div id="InnerLayer2" style="position:absolute; width:200px;
height:200px; background-color:#CCCCFF; z-index:3; left: 50px; top:
50px"></div>
</div>
</div>

</body>
</html>

Jul 23 '05 #30

P: n/a
VK
> [3]
...OuterLayer onclick="update(event.target, this, newContent)"...


Actually here is FF who doesn't act by ECMA, because it doesn't let you
forward an argument from the outer function to the inner one.
....onclick="update(event, this, newContent)... - this will fail
("event" is UOA - Undefined On Arrival :)
You have to pull out the needed properties right on the spot, or you
are out of luck. The fact that obj.onclick.arguments[0] works like a
charm - it shows that this might be not an error, but an intentional
block. But why?

Jul 23 '05 #31

P: n/a
On 25/05/2005 13:51, VK wrote:
1. About the nature of the event object in IE:
I'm not going to comment on this. As I said previously, it's entirely
irrelevant.

[snip]
Dear Michael, I know very well how to get event properties in a FF/IE
compatible way. [...]
But there seems to be some doubt about that, otherwise you wouldn't be
posting a question that I already answered.

[snip]
...OuterLayer onclick="update(event.target, this, newContent)"...
...
function update(tar, obj, content) {
/* It works, it's ECMA-obeyant, but the first argument is reserved for
POSSIBLE argument */


Only because *you've* chosen to reserve the first argument. Either you
didn't read my previous post, or you didn't understand it. I will try
one last time. If you don't get it this time, I give up.

Say that we're going to add this onclick event via addEventListener (I'm
skipping feature detection and whatnot for simplicity):

var outerLayer = document.getElementById('OuterLayer');

outerLayer.addEventListener('click', listener, false);

When listener is called, it will be passed the event object as it's
first argument, so we need a function along the lines of:

function listener(e) {
/* ... */
}

Now we call your update function with the following signature:

function update(object, content, event) {}

with

function listener(e) {
update(this, '...', e);
}

OK? That's simple enough.
Now instead, we'll use the onclick attribute. The process is exactly the
same (!) with only one difference: the user agent will create 'listener'
for us internally, with 'event' instead of 'e':

onclick="update(this, '...', event);"

That's it. Do you see? The onclick attribute just specifies code for the
body of a generated function. What you put in that function body is up
to you - you can pass the event object in any way you choose. It's your
decision.

I already said this in my previous post, and I think I've made it as
clear as I possibly can. If you don't understand, well, I'm really not
sure what else I can do, especially if you just keep repeating yourself
or going off on tangents, rather than helping me to help you.
Using what I wrote above, your update function would look something like:

/* The event argument is optional. If missing,
* the content will be prepended to the object
* unconditionally.
*/
function update(object, content, event) {
var target;

/* First, check if an event object was passed to the
* function. If so, attempt to obtain the target
* element of that event.
*/
if(event) {target = event.target || event.srcElement;}

/* If no target was found (because no event object
* was passed), OR the target was the object argument,
* prepend content to object.
*/
if(!target || (target == object)) {
object.innerHTML = content + object.innerHTML;
}
}

Even if you still haven't understood (and I hope to &deity; that you
have), just try what I've suggested. You'll see that it works.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #32

P: n/a
VK wrote:
The best trick for all this event mess so far I found is from Lasse
Reichstein Nielsen:
...
<li id="i" onclick="show(this, (event.target||event.srcElement))">Some
text*</li>
...
That is not the best way. Consider that, however unlikely, the `event'
reference is `undefined' or `null', this would result in a script error;
what you are relying on in the above is still non-standard host-specific
behavior.

The below `show' method, on the other hand, can check whether the passed
argument is `undefined' or `null' before accessing its properties. That
would result in:
function show(src,trg) {
if (src == trg) {
alert(src.id);
}
}
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
function show(src, e)
{
var trg = e && (e.target || e.srcElement);
if (trg && (src == trg))
{
alert(src.id);
}
}
</script>
...
<li id="i" onclick="show(this, event)">Some text*</li>
Works for IE 6.x and FF 1.0.3/4


And no more is for sure without change.
PointedEars
Jul 23 '05 #33

P: n/a
VK wrote:
[3]
...OuterLayer onclick="update(event.target, this, newContent)"...
Actually here is FF who doesn't act by ECMA, because it doesn't let you
forward an argument from the outer function to the inner one.


But it does.
...onclick="update(event, this, newContent)... - this will fail
("event" is UOA - Undefined On Arrival :)
No, it is not. Either your test case is flawed or your Firefox nightly
is buggy.
You have to pull out the needed properties right on the spot, or you
are out of luck.


No, it works long since without referring to properties of `event'
within the event handler attribute value and that did not change
to date.
PointedEars
--
When the power of love overcomes the love
of power, the world will know peace.
-- Jimi Hendrix
Jul 23 '05 #34

This discussion thread is closed

Replies have been disabled for this discussion.