Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #18049 > unrolled thread

Clone node with events

Started byCezary Tomczyk <cezary.tomczyk@gmail.com>
First post2013-01-10 12:33 +0100
Last post2013-01-13 22:07 -0800
Articles 8 — 5 participants

Back to article view | Back to comp.lang.javascript


Contents

  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

#18049 — Clone node with events

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2013-01-10 12:33 +0100
SubjectClone 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]


#18050

FromScott Sauyet <scott.sauyet@gmail.com>
Date2013-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]


#18094

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2013-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]


#18099

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-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]


#18115

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2013-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]


#18051

FromStefan Weiss <krewecherl@gmail.com>
Date2013-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]


#18095

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2013-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]


#18102

FromRobG <rgqld@iinet.net.au>
Date2013-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