87

Say I had a div#parent and I append and remove elements to it using jquery. How would I be able to detect when such an event happens on the div#parent element?

2

4 Answers 4

168

Don't use mutation events like DOMNodeInserted and DOMNodeRemoved.

Instead, use DOM Mutation Observers, which are supported in all modern browsers except IE10 and lower (Can I use). Mutation observers are intended to replace mutation events (which have been deprecated), as they have been found to have low performance due to flaws in its design.

var x = new MutationObserver(function (e) {
  if (e[0].removedNodes) console.log(1);
});

x.observe(document.getElementById('parent'), { childList: true });
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for answer, but Mutation Observers has a bad behaviour: I want to set observer to node which will be attached to tree later. I don't know the parent ( With 'DOMNodeRemoved' I could. Any ideas? I want node listen self destruction.
@DenisKolodin wow, I didn't notice this comment, sorry. For posterity's sake, that should be answered by this question. It does mean placing an event at the document level, but mutation events have such a large performance penalty it probably doesn't matter anyway.
not sure if this is worth mentioning in your answer as it doesn't directly answer this question, but custom elements have a disconnectedCallback
@Qantas94Heavy What do you mean? If performance penalty is real why are we recommended away from DOMNodeRemoved? I am also considering one on document level. Please see stackoverflow.com/questions/69426920/…
Note the isConnected prop on HTMLElements makes this a little nicer. var x = new MutationObserver(() => { console.log(element.isConnected) }); x.observe(element.parentElement, { childList: true });
|
40

Use Mutation Observers as suggested by @Qantas in his answer


Following methods are deprecated

You can use DOMNodeInserted and DOMNodeRemoved

$("#parent").on('DOMNodeInserted', function(e) {
    console.log(e.target, ' was inserted');
});

$("#parent").on('DOMNodeRemoved', function(e) {
    console.log(e.target, ' was removed');
});

MDN Docs

5 Comments

Mutation events are deprecated, this answer should no longer be the correct one. Mutation Observers were designed as a replacement for Mutation Events, so Qantas answer is the correct one. developer.mozilla.org/en-US/docs/Web/Guide/Events/… and developer.mozilla.org/en-US/docs/Web/API/MutationObserver
used this method, but with config only to listen child dom updated , ref: academy.byidmore.com/post/…
Image
It may be slow and a bad idea for code in production, but this looks like the only method that works synchronously (unlike MutationObserver). This is a good option for debugging when nothing else is suitable, for example, when trying to find the line of code that changed the DOM.
@satpal Is it possible to combine these, instead of having two sets of code? If DOMNodeInserted or DOMNodeRemoved, function() { etc.
If performance penalty is real why are we recommended away from DOMNodeRemoved? I am also considering one on document level. Please see stackoverflow.com/questions/69426920/…
5

It wouldn't let me comment below on the top answer but to answer your question @DenisKolodin, in order to listen for self-destruction, you can do something like this:

function watchElForDeletion(elToWatch, callback, parent = document.querySelector('body')){
  const observer = new MutationObserver(function (mutations) {

    // loop through all mutations
    mutations.forEach(function (mutation) {

        // check for changes to the child list
        if (mutation.type === 'childList') {

            // check if anything was removed and if the specific element we were looking for was removed
            if (mutation.removedNodes.length > 0 && mutation.removedNodes[0] === elToWatch) {
                callback();
            }
        }
    });
  });

  // start observing the parent - defaults to document body
  observer.observe(parent, { childList: true });
};

It defaults to the parent being the body element and only runs the callback if the specific element you're looking for is deleted.

1 Comment

This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
3

You should bind DOMSubtreeModified event

$("#parent").bind("DOMSubtreeModified",function(){
  console.log('changed');
});

http://jsfiddle.net/WQeM3/

2 Comments

DOMSubtreeModified events are deprecated: Can I Use
If performance penalty is real why are we recommended away from DOMNodeRemoved? I am also considering one on document level. Please see stackoverflow.com/questions/69426920/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.