Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #18049 > unrolled thread
| Started by | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| First post | 2013-01-10 12:33 +0100 |
| Last post | 2013-01-13 22:07 -0800 |
| Articles | 8 — 5 participants |
Back to article view | Back to comp.lang.javascript
Clone node with events Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-10 12:33 +0100
Re: Clone node with events Scott Sauyet <scott.sauyet@gmail.com> - 2013-01-10 07:30 -0800
Re: Clone node with events Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-12 22:57 +0100
Re: Clone node with events Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-13 15:07 +0100
Re: Clone node with events Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-16 20:50 +0100
Re: Clone node with events Stefan Weiss <krewecherl@gmail.com> - 2013-01-10 17:15 +0100
Re: Clone node with events Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-12 23:00 +0100
Re: Clone node with events RobG <rgqld@iinet.net.au> - 2013-01-13 22:07 -0800
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-10 12:33 +0100 |
| Subject | Clone node with events |
| Message-ID | <kcm8um$8pi$1@speranza.aioe.org> |
"Cloning a node copies all of its attributes and their values but does not copy event listeners." - https://developer.mozilla.org/en-US/docs/DOM/Node.cloneNode Any idea how to in an efficient and proper way clone node with events? -- Cezary Tomczyk http://www.ctomczyk.pl/
[toc] | [next] | [standalone]
| From | Scott Sauyet <scott.sauyet@gmail.com> |
|---|---|
| Date | 2013-01-10 07:30 -0800 |
| Message-ID | <3cfb8a75-8706-42d6-9cc5-fbd293ee29f9@10g2000yqo.googlegroups.com> |
| In reply to | #18049 |
Cezary Tomczyk wrote:
> "Cloning a node copies all of its attributes and their values but does
> not copy event listeners." -https://developer.mozilla.org/en-US/docs/DOM/Node.cloneNode
>
> Any idea how to in an efficient and proper way clone node with events?
One problem is that in general it's not always clear that events
should be cloned, or that if they are cloned that they will now do
what you'd expect.
If you have this structure:
Div 1
Div 2
Checkbox 2.1
EventListener 2.1.1 : toggles Div 1
Div 2.2
Checkbox 2.3
EventListener 2.3.1 : toggles Div 2.2
And want to clone Div 2, all its children and their events, it mostly
makes sense:
Div 2a
Checkbox 2.1a
EventListener 2.1.1a : toggles Div 1
Div 2.2a
Checkbox 2.3a
EventListener 2.3.1a : ??
But what would EventListener 2.3.1a do? Should it toggle Div 2.2?
That seems strange. Probably toggling Div 2.2a makes more sense, but
how we would we distinguish this from EventListener 2.1.1a, which
doesn't change it's target? And of course this doesn't even address
the fact that we don't actually have a way to convert an event
listening function that toggles the visibility of one DIV into one
that toggles the visibility of another. So we don't really know what
to do or how to do it. :-)
So event listeners that were copied would have to be smart enough to
determine their behavior based on where they were triggered. It gets
ugly.
-- Scott
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-12 22:57 +0100 |
| Message-ID | <kcsm8o$8of$1@speranza.aioe.org> |
| In reply to | #18050 |
W dniu 2013-01-10 16:30, Scott Sauyet pisze: > Cezary Tomczyk wrote: [...] >> Any idea how to in an efficient and proper way clone node with events? > > One problem is that in general it's not always clear that events > should be cloned, or that if they are cloned that they will now do > what you'd expect. > If you have this structure: > > Div 1 > Div 2 > Checkbox 2.1 > EventListener 2.1.1 : toggles Div 1 > Div 2.2 > Checkbox 2.3 > EventListener 2.3.1 : toggles Div 2.2 > > And want to clone Div 2, all its children and their events, it mostly > makes sense: > > Div 2a > Checkbox 2.1a > EventListener 2.1.1a : toggles Div 1 > Div 2.2a > Checkbox 2.3a > EventListener 2.3.1a : ?? > > But what would EventListener 2.3.1a do? Should it toggle Div 2.2? > That seems strange. Probably toggling Div 2.2a makes more sense, but > how we would we distinguish this from EventListener 2.1.1a, which > doesn't change it's target? And of course this doesn't even address > the fact that we don't actually have a way to convert an event > listening function that toggles the visibility of one DIV into one > that toggles the visibility of another. So we don't really know what > to do or how to do it. :-) Yes, that situation shows that cloning with events is not so clear. But consider this simple example: http://jsfiddle.net/JpLx2/ All I need here is to just copy attached events from old_node to new_node, but seems that is not so easy to do. This could be possible done by, for example, adding some wrapper to event methods and then use it. On the other hand I found http://www.w3.org/TR/2001/WD-DOM-Level-3-Events-20010823/events.html#Events-EventListenerList, but seems that it is not implemented, for example, in Firefox 17.0.1 and Opera 12.12. Probably in other browsers also is not implemented :-( > So event listeners that were copied would have to be smart enough to > determine their behavior based on where they were triggered. It gets > ugly. Seems it is not so easy case ;-) -- Cezary Tomczyk http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-01-13 15:07 +0100 |
| Message-ID | <4079901.yXqkfi7LMG@PointedEars.de> |
| In reply to | #18094 |
Cezary Tomczyk wrote: > […] > consider this simple example: > > http://jsfiddle.net/JpLx2/ > > All I need here is to just copy attached events from old_node to > new_node, but seems that is not so easy to do. This could be possible > done by, for example, adding some wrapper to event methods and then use > it. First of all, you are _not_ copying events. You could be copying event *listeners*, but all you would copy in ECMAScript would be *references* to Function instances. So there is no problem here. You have a reference to a Function instance, and the “click” event bubbles in all know DOM implementations. So, as already suggested, you should use event delegation, in particular use event bubbling: Add to a common ancestor element a listener for that event that does actions only for specific event targets. When a cloned target receives that event, it has no listener for it; since the event bubbles, it will be handled by the ancestor element which has a listener for it. BTW, you should not be using attachEvent() as an alternative to addEventListener(): <http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html> > On the other hand I found > http://www.w3.org/TR/2001/WD-DOM-Level-3 > Events-20010823/events.html#Events-EventListenerList, > but seems that it is not implemented, for example, in Firefox 17.0.1 and > Opera 12.12. Probably in other browsers also is not implemented :-( Neither is it implemented in WebKit WebCore as of Chromium 22. You are referring to an *old* Working Draft. The *current* Working Draft for W3C DOM Level 3 Events is available at <http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120906/>. You will notice that the EventTarget interface no longer has an “eventListeners” attribute of type “EventListenerList”, and that the “EventListenerList” interface has been removed: <http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120906/#interface- EventTarget> And it would seem that no replacement for that attribute or interface has been suggested yet. However, with proprietary event handler properties (called “traditional event registration” on QuirksMode.org) now perhaps going to be a Web standard with the HTML5 API, for elements and events for which only one event listener has been added, you could use those properties to retrieve the primary event listener for an event on an element: <http://www.w3.org/html/wg/drafts/html/master/index.html#ix-event-handlers> <http://www.w3.org/html/wg/drafts/html/master/webappapis.html#event- handlers> While that has worked even before HTML5 (jsx.dom.*EventListener() are based on it), I recommend you use event bubbling here. -- PointedEars Twitter: @PointedEars2 Please do not Cc: me. / Bitte keine Kopien per E-Mail.
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-16 20:50 +0100 |
| Message-ID | <kd7096$78e$1@speranza.aioe.org> |
| In reply to | #18099 |
W dniu 2013-01-13 15:07, Thomas 'PointedEars' Lahn pisze: > Cezary Tomczyk wrote: [...] > First of all, you are _not_ copying events. You could be copying event > *listeners*, but all you would copy in ECMAScript would be *references* to > Function instances. > > So there is no problem here. You have a reference to a Function instance, > and the “click” event bubbles in all know DOM implementations. So, as > already suggested, you should use event delegation, in particular use event > bubbling: Add to a common ancestor element a listener for that event that > does actions only for specific event targets. When a cloned target receives > that event, it has no listener for it; since the event bubbles, it will be > handled by the ancestor element which has a listener for it. Yes, that's a good idea and I know that. But, seems that I was misunderstood. I want to clone node where I do not know if there are attached event listeners or not. The only one thing that can I do is write wrapper on addEventListener and attachEvent to collect all event listeners and reattach them to specified node after cloning. > BTW, you should not be using attachEvent() as an alternative to > addEventListener(): > <http://www.quirksmode.org/blog/archives/2005/08/addevent_consid.html> Right. I should use "else if". >> On the other hand I found >> http://www.w3.org/TR/2001/WD-DOM-Level-3 >> Events-20010823/events.html#Events-EventListenerList, >> but seems that it is not implemented, for example, in Firefox 17.0.1 and >> Opera 12.12. Probably in other browsers also is not implemented :-( > > Neither is it implemented in WebKit WebCore as of Chromium 22. You are > referring to an *old* Working Draft. The *current* Working Draft for W3C > DOM Level 3 Events is available at > > <http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120906/>. Ah, yes. My link is very old :/ > You will notice that the EventTarget interface no longer has an > “eventListeners” attribute of type “EventListenerList”, and that the > “EventListenerList” interface has been removed: > > <http://www.w3.org/TR/2012/WD-DOM-Level-3-Events-20120906/#interface- > EventTarget> > > And it would seem that no replacement for that attribute or interface has > been suggested yet. > > However, with proprietary event handler properties (called “traditional > event registration” on QuirksMode.org) now perhaps going to be a Web > standard with the HTML5 API, for elements and events for which only one > event listener has been added, you could use those properties to retrieve > the primary event listener for an event on an element: > > <http://www.w3.org/html/wg/drafts/html/master/index.html#ix-event-handlers> > <http://www.w3.org/html/wg/drafts/html/master/webappapis.html#event- > handlers> > > While that has worked even before HTML5 (jsx.dom.*EventListener() are based > on it), I recommend you use event bubbling here. I know that I can use event bubbling, but as I mentioned, sometimes I do not know if node has an attached any listeners or not. But I think that I can do something like I described above. Heh, I event found your old post http://www.velocityreviews.com/forums/t936046-list-events-of-an-element-wired-up-with-addeventlistener.html, but this is what I meant :-) -- Cezary Tomczyk http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | Stefan Weiss <krewecherl@gmail.com> |
|---|---|
| Date | 2013-01-10 17:15 +0100 |
| Message-ID | <kcmpfg$pli$1@news.albasani.net> |
| In reply to | #18049 |
On 2013-01-10 12:33, Cezary Tomczyk wrote:
> Any idea how to in an efficient and proper way clone node with events?
That doesn't seem like a good idea in the first place (for the reason
Scott mentioned), but maybe there's a better way. When you have a number
of elements that should react in a similar way to an event, consider
using event delegation instead of separate listeners for each element.
Simply put, that means attaching one listener to a common parent
element, and resolving the event target from there. This works
especially well for click events; other event types (like mouseover,
mouseout) can be a little more tricky. Some events do not bubble at all
(focus, blur, change, etc).
If you can't use event delegation, use a wrapper function to
create/clone the element and attach the listeners at the same time:
function handleFocus (evt) {}
function makeInput (node) {
var input = node ? node.cloneNode()
: document.createElement("input");
input.addEventListener("focus", handleFocus);
return input;
}
- stefan
[toc] | [prev] | [next] | [standalone]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-01-12 23:00 +0100 |
| Message-ID | <kcsme8$8of$2@speranza.aioe.org> |
| In reply to | #18051 |
W dniu 2013-01-10 17:15, Stefan Weiss pisze:
> On 2013-01-10 12:33, Cezary Tomczyk wrote:
>> Any idea how to in an efficient and proper way clone node with events?
>
> That doesn't seem like a good idea in the first place (for the reason
> Scott mentioned), but maybe there's a better way. When you have a number
> of elements that should react in a similar way to an event, consider
> using event delegation instead of separate listeners for each element.
Yes, I know event delegation. They are powerful :-)
> Simply put, that means attaching one listener to a common parent
> element, and resolving the event target from there. This works
> especially well for click events; other event types (like mouseover,
> mouseout) can be a little more tricky. Some events do not bubble at all
> (focus, blur, change, etc).
>
> If you can't use event delegation, use a wrapper function to
> create/clone the element and attach the listeners at the same time:
>
> function handleFocus (evt) {}
>
> function makeInput (node) {
> var input = node ? node.cloneNode()
> : document.createElement("input");
> input.addEventListener("focus", handleFocus);
> return input;
> }
That is the only way, as I see, at this moment. But this is useful when
you know what type of events are attached. Otherwise, as I mentioned in
reply to Scott, it is better to write some wrapper to event methods and
use collected data (I mean attached events) to attach them again after
replacing element.
--
Cezary Tomczyk
http://www.ctomczyk.pl/
[toc] | [prev] | [next] | [standalone]
| From | RobG <rgqld@iinet.net.au> |
|---|---|
| Date | 2013-01-13 22:07 -0800 |
| Message-ID | <60045f36-744a-4a09-9236-31af3d4ea279@googlegroups.com> |
| In reply to | #18049 |
On Thursday, January 10, 2013 9:33:45 PM UTC+10, Cezary Tomczyk wrote: > "Cloning a node copies all of its attributes and their values but does > not copy event listeners." - > > https://developer.mozilla.org/en-US/docs/DOM/Node.cloneNode That is not true: in–line event handlers are cloned, as are those added using attachEvent (in IE at least). Only listeners added using addEventListener or as properties (e.g. node.onchange = …) are not cloned. -- Rob
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.javascript
csiph-web