views:

161

answers:

2

What behavior should I expect if I delete a DOM element that was used to start an event bubble, or whose child started the event bubble - will it continue to bubble if the element is removed?

For example - lets say you have a table, and want to detect click events on the table cells. Another piece of JS has executed an AJAX request that will eventually replace the table, in full, once the request is complete.

What happens if I click the table, and immediately after the table gets replaced by a successful completion of an AJAX request? I ask because I am seeing some behavior where the click events don't seem to be bubbling - but it is hard to duplicate.

I am watching the event on a parent element of the table (instead of attaching the event to every TD), and it just doesn't seem to reach it sometimes.

+2  A: 

Yes, it should continue to propagate. Events have no real attachment to the event they fired on, except for the target property. When you remove the element, the internal code propagating the event should not have any "awareness" that the original element has gone from the visible document.

As an aside, using removeChild will not delete an element right away, it just detaches it from the document tree. An element should only be deleted/garbage collected when there are no references to it. Therefore, it's possible that the element could still be referred to via the event.target property and even re-inserted before being garbage collected. I haven't tried it though, so it's just speculation.


T.J. Crowder's comment made me decide to knock up a quick example. I was right on both counts, it does bubble and you can still get a reference to the removed node using event.target.

http://jsbin.com/ofese/2/


As T.J. discovered, that is not the case in IE. But the DOM Level 2 Events specification does define it as correct behavior [emphasis mine]:.

Events which are designated as bubbling will initially proceed with the same event flow as non-bubbling events. The event is dispatched to its target EventTarget and any event listeners found there are triggered. Bubbling events will then trigger any additional event listeners found by following the EventTarget's parent chain upward, checking for any event listeners registered on each successive EventTarget. This upward propagation will continue up to and including the Document. EventListeners registered as capturers will not be triggered during this phase. The chain of EventTargets from the event target to the top of the tree is determined before the initial dispatch of the event. If modifications occur to the tree during event processing, event flow will proceed based on the initial state of the tree.

Andy E
@Andy: Actually, no, it depends on the browser. I decided to stick around and try it, see my answer.
T.J. Crowder
@T.J. lol I knew I should have tested IE. It pays to be thorough, I suppose, +1 for you! Still, I can't understand why IE would do this (although it doesn't really surprise me that much), it goes against all logic if you ask me. Like I said in my answer, with `removeChild`, the element isn't deleted entirely, just detached from the DOM tree, and can be put back in. It just makes no sense to cancel the event.
Andy E
@Andy: Yeah, *always* test with IE, so many things are different. :-) I can sort of see their interpretation, using this (entirely hypothetical logic): 1. Dispatcher receives event 2. Dispatcher dispatches event on element 3. Handler removes element 4. Dispatcher checks `cancelBubble` flag and it's false 5. Dispatcher looks at `element.parentNode` -- but it's `null`; stop dispatching. Whereas the other browsers seem to grab the entire ancestry *before* they start dispatching the event. Barring the specification being clear about what should happen, I don't see either behavior as wrong. :-)
T.J. Crowder
@T.J. yeah, the w3c appears to be on my side ;-) I've added a quote from the level 2 spec just for thread completion. I have to say I do think it makes more sense this way, event bubbling is there for a reason and it shouldn't be like the event "never happened" for the the chain of ancestors just because the element is removed from the tree.
Andy E
@Andy: Excellent, thanks for the quote and reference! Poor Microsoft. :-) And that seems like the best way to define the bubbling, too, glad they did that in DOM2.
T.J. Crowder
Nice find on the DOM2 event specification. +1
Matt
Thanks @Matt, it turned out to be a very interesting question :-)
Andy E
+7  A: 
T.J. Crowder
+1 and the green check for being so thorough!
Matt
@T.J. Brilliant detail and summary, the perfect answer, shame I can't give another +1 lol.
Andy E
@Andy: LOL, thanks -- and thanks for finding the DOM2 info!
T.J. Crowder