<ul><li><ul><li>... onclick() only for one node ?

J

Jörg Weule

Hello,

at <ul><li><ul><li>...</li></ul></li></ul> I got the click event on the
whole tree and want to process the event for only on one node.

How can i stop the event processing calling my function for any node at
the hirachie?

With kind regards

Jörg
 
A

Arno Welzel

Jörg Weule, 2011-11-25 16:10:
Hello,

at <ul><li><ul><li>...</li></ul></li></ul> I got the click event on the
whole tree and want to process the event for only on one node.

How can i stop the event processing calling my function for any node at
the hirachie?

You have to stop event bubbling in your handler.
 
T

Thomas 'PointedEars' Lahn

Jörg Weule said:
at <ul><li><ul><li>...</li></ul></li></ul> I got the click event on the
whole tree and want to process the event for only on one node.

How can i stop the event processing calling my function for any node at
the hirachie?

If this is really only for one node, you can call the stopPropagation()
method (standards-compliant) or set the event object's `cancelBubble'
property to `true' (MSHTML) in the event listener. However, the drawback of
this is that *no* element "upwards" in the tree will receive that event
then, which may not be wanted.

If the latter is important, or if this instead for multiple nodes at the
same nesting level, you should not do this. For then you need to stop event
progagation at every child node. This comparably inefficient approach is
propagated by, e. g., jQuery and other selector-based libraries, where you
would first select elements by a criterion (usually a `class' attribute
value) and then add an event listener to each matching element.

It is therefore better (for bubbling events like `click') to add only one
event listener to an ancestor element (here: the `ul' element) in which you
compare the event target against the object the event has bubbled up to
(e.target == this, or e.srcElement == this in MSHTML [do not use
attachEvent()]), and only perform the action for relevant event targets. In
case of remaining ambiguity, you can use e. g. the event target's `class'
attribute value as well. Be aware that text nodes can be event targets,
too.


PointedEars
 
J

Jörg Weule

thanks for that.

Not I can write <div onClick()="doMyFunction(event.target)"> to get the
inner clicked element but Firefox is not accepting

var l = document.createElement("li");
l.onclick = function(){ doMyFunction(event.target) ; } ;

Here I got "event is not defined".

Jörg

Jörg Weule said:
at<ul><li><ul><li>...</li></ul></li></ul> I got the click event on the
whole tree and want to process the event for only on one node.

How can i stop the event processing calling my function for any node at
the hirachie?

If this is really only for one node, you can call the stopPropagation()
method (standards-compliant) or set the event object's `cancelBubble'
property to `true' (MSHTML) in the event listener. However, the drawback of
this is that *no* element "upwards" in the tree will receive that event
then, which may not be wanted.

If the latter is important, or if this instead for multiple nodes at the
same nesting level, you should not do this. For then you need to stop event
progagation at every child node. This comparably inefficient approach is
propagated by, e. g., jQuery and other selector-based libraries, where you
would first select elements by a criterion (usually a `class' attribute
value) and then add an event listener to each matching element.

It is therefore better (for bubbling events like `click') to add only one
event listener to an ancestor element (here: the `ul' element) in which you
compare the event target against the object the event has bubbled up to
(e.target == this, or e.srcElement == this in MSHTML [do not use
attachEvent()]), and only perform the action for relevant event targets. In
case of remaining ambiguity, you can use e. g. the event target's `class'
attribute value as well. Be aware that text nodes can be event targets,
too.


PointedEars
 
M

Martin Honnen

Jörg Weule said:
Not I can write <div onClick()="doMyFunction(event.target)"> to get the
inner clicked element but Firefox is not accepting

var l = document.createElement("li");
l.onclick = function(){ doMyFunction(event.target) ; } ;

Here I got "event is not defined".

The proper approach is
var l = document.createElement("li");
l.onclick = function(evt) {
doMyFunction(evt.target);
};
at least for Mozilla, Opera, Safari, Chrome and IE 9 (in IE 9 mode).
For earlier IE versions you need
var l = document.createElement("li");
l.onclick = function(evt) {
var event = evt || window.event;
doMyFunction(event.target || event.srcElement);
};
 
J

Jukka K. Korpela

2011-11-25 17:10 said:
at <ul><li><ul><li>...</li></ul></li></ul> I got the click event on the
whole tree and want to process the event for only on one node.

Applying the techniques explained at
http://www.quirksmode.org/js/events_order.html
you could write

var l = document.createElement("li");
l.onclick = handler;
function handler(e)
{
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
// do the real handling here
}
 
J

Jörg Weule

The proper approach is
var l = document.createElement("li");
l.onclick = function(evt) {
doMyFunction(evt.target);
};
at least for Mozilla, Opera, Safari, Chrome and IE 9 (in IE 9 mode).
For earlier IE versions you need
var l = document.createElement("li");
l.onclick = function(evt) {
var event = evt || window.event;
doMyFunction(event.target || event.srcElement);
};
Of cause: l.onclick = function(evt) {...}
One signal handler at the top ul sounds reasonable and works great.

Thanks a lot.

Jörg
 
T

Thomas 'PointedEars' Lahn

Martin said:
The proper approach is
var l = document.createElement("li");
l.onclick = function(evt) {
doMyFunction(evt.target);
};
at least for Mozilla, Opera, Safari, Chrome and IE 9 (in IE 9 mode).
For earlier IE versions you need
var l = document.createElement("li");
l.onclick = function(evt) {
var event = evt || window.event;
doMyFunction(event.target || event.srcElement);
};

If one uses the more error-prone boolean shortcut syntax instead of `typeof'
testing, it should be

l.onclick = function(evt) {
var event = evt || window.event;
if (event)
{
doMyFunction(event.target || event.srcElement);
}
};

as one should not assume that if `evt' type-converts to false,
`window.event' must refer to an object. However, that approach is
proprietary, even though for historical reasons it is probably most
compatible.

The standards-compliant approach is, and the proper approach has become

l.addEventListener("click", function(evt) {
doMyFunction(evt.target);
}, false);

since IE/MSHTML 9 supports it in Standards Mode. Until that remains less
compatible (there is still IE/MSHTML < 9), using a wrapper method like
jsx.dom.addEventListener() [1] is recommended, so as not to overwritethe
primary event listener if one has been added, e. g., with the `onclick'
attribute, and not to interfere with the order of event listeners of an
element.


PointedEars
___________
[1]
<http://pointedears.de/websvn/filedetails.php?repname=JSX&path=/trunk/dom/events.js>
 
T

Thomas 'PointedEars' Lahn

Jukka said:
Applying the techniques explained at
http://www.quirksmode.org/js/events_order.html
you could write

var l = document.createElement("li");
l.onclick = handler;
function handler(e)
{
if (!e) var e = window.event;

That `VariableDeclaration' is pointless; it also reduces runtime efficiency
slightly. The Variable Object (or the Variable Environment) already had the
variable `e' instantiated per the function's argument list, so the
VariableDeclaration has no effect (other than checking for a previous
binding, which is what reduces runtime efficiency). [ES 5.1, section 10.5]
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
// do the real handling here
}

One should *either* attempt to set the `cancelBubble' property to `true'
*or* attempt to call the stopPropagation() method, depending on what is the
result of a feature test, because `e' refers to a host object and should not
be accidentally augmented. To that end, jsx.dom.createEventListener()
solves this with

e2.stopPropagation = (function(e) {
if (jsx_object.isMethod(e, "stopPropagation"))
{
return function() {
e.stopPropagation();
};
}

if (typeof e.cancelBubble != "undefined")
{
return function() {
e.cancelBubble = true;
};
}
})(e);

`e2' is a reference to a native user-defined object that is passed in place
of the event host object (referred to by `e') to the wrapped event listener
then (revision 233, line 459):

return f.call(this, e2);

Which allows to call e.stopPropagation() in the wrapped listener (f)
regardless which DOM implementation is supported.

A similar wrapper method exists for the preventDefault() method. But it
turns out that the `returnValue' property, which is the proprietary
replacement for the preventDefault() method, cannot be feature-tested.
So `returnValue' is used if preventDefault() is unavailable regardless.

The original event object is available with the `originalEvent' property
of the object referred to by `e2'.

AISB, the proprietary event handler properties should be avoided.


PointedEars
 
J

J.R.

Jukka said:
Applying the techniques explained at
http://www.quirksmode.org/js/events_order.html
you could write

var l = document.createElement("li");
l.onclick = handler;
function handler(e)
{
if (!e) var e = window.event;

That `VariableDeclaration' is pointless; it also reduces runtime efficiency
slightly. The Variable Object (or the Variable Environment) already had the
variable `e' instantiated per the function's argument list, so the
VariableDeclaration has no effect (other than checking for a previous
binding, which is what reduces runtime efficiency). [ES 5.1, section 10.5]

ACK as to 'VariableDeclaration is pointless', although that reduction in
runtime efficiency, if noticeable / measurable, should be dependent on
the actual JavaScript Engine in use.
One should *either* attempt to set the `cancelBubble' property to `true'
*or* attempt to call the stopPropagation() method, depending on what is the
result of a feature test, because `e' refers to a host object and should not
be accidentally augmented. To that end, jsx.dom.createEventListener()
solves this with

e2.stopPropagation = (function(e) {
if (jsx_object.isMethod(e, "stopPropagation"))
{
return function() {
e.stopPropagation();
};
}

if (typeof e.cancelBubble != "undefined")
{
return function() {
e.cancelBubble = true;
};
}
})(e);

"Either cancelBubble property or stopPropagation() method" means only
one check is necessary, not both, as there is not a 3rd option. So:

e2.cancelPropagation = function (e) {
e = e || window.event;
if (typeof e.stopPropagation !== 'undefined') { // W3C standard
e.stopPropagation();
} else { e.cancelBubble = true; } // IE
};

`e2' is a reference to a native user-defined object that is passed in place
of the event host object (referred to by `e') to the wrapped event listener
then (revision 233, line 459):

return f.call(this, e2);

Which allows to call e.stopPropagation() in the wrapped listener (f)
regardless which DOM implementation is supported.

A similar wrapper method exists for the preventDefault() method. But it
turns out that the `returnValue' property, which is the proprietary
replacement for the preventDefault() method, cannot be feature-tested.
So `returnValue' is used if preventDefault() is unavailable regardless.
someObj.cancelDefault = function (e) {
e = e || window.event;
if (typeof e.preventDefault !== 'undefined') { // W3C standard
e.preventDefault();
} else { e.returnValue = false; } // IE
};

<snip>
 
J

Jukka K. Korpela

2011-11-26 1:57 said:
"Either cancelBubble property or stopPropagation() method" means only
one check is necessary, not both, as there is not a 3rd option.

And, in reality, as the page I mentioned says, you can assign to
e.cancelBubble without a check, as adding a property to an object causes
no real harm.

There are of course people who just have to complain about any code that
solves a problem, claiming it to be risky, with some vague abstract
arguments. They don't identify any real harm. And the added code or
different, longer, more complex code they may suggest of course causes
much bigger risks than those it is claimed to avoid.
 
T

Thomas 'PointedEars' Lahn

J.R. said:
Jukka said:
2011-11-25 17:10, Jörg Weule wrote:
at<ul><li><ul><li>...</li></ul></li></ul> I got the click event on the
whole tree and want to process the event for only on one node.

Applying the techniques explained at
http://www.quirksmode.org/js/events_order.html
you could write

var l = document.createElement("li");
l.onclick = handler;
function handler(e)
{
if (!e) var e = window.event;

That `VariableDeclaration' is pointless; it also reduces runtime
efficiency slightly. The Variable Object (or the Variable Environment)
already had the variable `e' instantiated per the function's argument
list, so the VariableDeclaration has no effect (other than checking for a
previous binding, which is what reduces runtime efficiency). [ES 5.1,
section 10.5]

ACK as to 'VariableDeclaration is pointless', although that reduction in
runtime efficiency, if noticeable / measurable, should be dependent on
the actual JavaScript Engine in use.

There are only two JavaScript engines (in different languages and versions).
Whether the difference is noticeable depends not only on the ECMAScript
implementation. However, a conforming implementation must implement that
algorithm one way or the other, so there is without doubt a reduction in
runtime efficiency.
"Either cancelBubble property or stopPropagation() method" means only
one check is necessary, not both, as there is not a 3rd option.

You are mistaken.
So:

e2.cancelPropagation = function (e) {
e = e || window.event;

Inefficient and error-prone.
if (typeof e.stopPropagation !== 'undefined') { // W3C standard

Error-prone and insufficient.
e.stopPropagation();
} else { e.cancelBubble = true; } // IE
};

That would augment the host object referred to by `e' if it did not have a
`cancelBubble' property.
someObj.cancelDefault = function (e) {
e = e || window.event;

Inefficient and error-prone.
if (typeof e.preventDefault !== 'undefined') { // W3C standard

Error-prone and insufficient.
e.preventDefault();
} else { e.returnValue = false; } // IE
};

You are missing the point, which is that an exception to the rule must be
made with this property. Your "IE" also is an oversimplification. You
would have known all this had you read my postings in this thread more
carefully.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Jukka said:
2011-11-26 1:57 said:
"Either cancelBubble property or stopPropagation() method" means only
one check is necessary, not both, as there is not a 3rd option.

And, in reality, as the page I mentioned says, you can assign to
e.cancelBubble without a check, as adding a property to an object causes
no real harm.

There are of course people who just have to complain about any code that
solves a problem, […]

Your arrogance is the cause of your ignorance, which blinds you for the
possibilities that await you.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,830
Latest member
ZADIva7383

Latest Threads

Top