jQuery - Trigger event when an element is removed from the DOM

160,275

Solution 1

Just checked, it is already built-in in current version of JQuery:

jQuery - v1.9.1

jQuery UI - v1.10.2

$("#myDiv").on("remove", function () {
    alert("Element was removed");
})

Important: This is functionality of Jquery UI script (not JQuery), so you have to load both scripts (jquery and jquery-ui) to make it work. Here is example: http://jsfiddle.net/72RTz/

Solution 2

You can use jQuery special events for this.

In all simplicity,

Setup:

(function($){
  $.event.special.destroyed = {
    remove: function(o) {
      if (o.handler) {
        o.handler()
      }
    }
  }
})(jQuery)

Usage:

$('.thing').bind('destroyed', function() {
  // do stuff
})

Addendum to answer Pierre and DesignerGuy's comments:

To not have the callback fire when calling $('.thing').off('destroyed'), change the if condition to: if (o.handler && o.type !== 'destroyed') { ... }

Solution 3

You can bind to the DOMNodeRemoved event (part of DOM Level 3 WC3 spec).

Works in IE9, latest releases of Firefox and Chrome.

Example:

$(document).bind("DOMNodeRemoved", function(e)
{
    alert("Removed: " + e.target.nodeName);
});

You can also get notification when elements are inserting by binding to DOMNodeInserted

Solution 4

There is no built-in event for removing elements, but you can create one by fake-extending jQuery's default remove method. Note that the callback must be called before actually removing it to keep reference.

(function() {
    var ev = new $.Event('remove'),
        orig = $.fn.remove;
    $.fn.remove = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

$('#some-element').bind('remove', function() {
    console.log('removed!');
    // do pre-mortem stuff here
    // 'this' is still a reference to the element, before removing it
});

// some other js code here [...]

$('#some-element').remove();

Note: some problems with this answer have been outlined by other posters.

  1. This won't work when the node is removed via html() replace() or other jQuery methods
  2. This event bubbles up
  3. jQuery UI overrides remove as well

The most elegant solution to this problem seems to be: https://stackoverflow.com/a/10172676/216941

Solution 5

Hooking .remove() is not the best way to handle this as there are many ways to remove elements from the page (e.g. by using .html(), .replace(), etc).

In order to prevent various memory leak hazards, internally jQuery will try to call the function jQuery.cleanData() for each removed element regardless of the method used to remove it.

See this answer for more details: javascript memory leaks

So, for best results, you should hook the cleanData function, which is exactly what the jquery.event.destroyed plugin does:

http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js

Share:
160,275

Related videos on Youtube

sa125
Author by

sa125

Updated on August 11, 2021

Comments

  • sa125
    sa125 over 2 years

    I'm trying to figure out how to execute some js code when an element is removed from the page:

    jQuery('#some-element').remove(); // remove some element from the page
    /* need to figure out how to independently detect the above happened */
    

    is there an event tailored for that, something like:

    jQuery('#some-element').onremoval( function() {
        // do post-mortem stuff here
    });
    
    • Natrium
      Natrium about 14 years
      out of curiousity, what would want to do with the element that has been removed?
    • sa125
      sa125 about 14 years
      I have an element that independently attaches itself to the piece I remove, so I want to detect when that piece is gone to eliminate that element as well. I could re-design the whole thing, but accomplishing the above will save me a lot of time (and code).
  • user113716
    user113716 about 14 years
    +1 for this idea. Though you could also extend jQuery (plugin style) in order to get a more standard jQuery call like: $('.itemToRemove').customRemove();. You could also make it so that it accepts a callback as a parameter.
  • meyertee
    meyertee about 13 years
    Thanks for that! One little addition: because the remove-event bubbles up, you'd also receive it when a child is removed, so better write the handler that way: $('#some-element').bind('remove', function(ev) { if (ev.target === this) { console.log('removed!'); } });
  • fturtle
    fturtle almost 13 years
    This didn't work out of the box for me - I had to return the result from orig.apply.
  • Rob
    Rob over 12 years
    This is not an accurate answer. See my answer
  • Will Morgan
    Will Morgan over 12 years
    Actually, @Adam, it is, but it's cross browser compatible. With meyertee/fturtle's additions it's a perfectly reliable solution, as long as you only remove elements with this method, rather than modifying/emptying HTML etc. For something more flexible, yes DOM mutation events are fine but I've been sceptic of them as you should be listening for business events in an app, not DOM ones whose structure is likely to change with further development. Also, subscribing to DOM mutation events means your program is potentially susceptible to lagging in complex DOM hierarchies.
  • Rob
    Rob over 12 years
    My only diagreement on the accuracy is the statement - 'there is no built in event for removing elements' --- there IS a built in event for browsers that implement Level 3 DOM events (as detailed in my answer).
  • Kai Aragaki
    Kai Aragaki over 12 years
    While this will detect elements removed using the 'remove' function, it will fail to detect elements removed by other means (e.g. using jQuery's html, replace, etc). Please, see my answer for more complete solution.
  • Petr Vostrel
    Petr Vostrel about 12 years
    This insight about cleanData was very helpful to me! Thank you very much, Joe :)
  • antti_s
    antti_s about 12 years
    Really nice solution. Ben Alman has a nice writeup about special events for more info: benalman.com/news/2010/03/jquery-special-events
  • Matt Wonlaw
    Matt Wonlaw almost 12 years
    Note: "Adding DOM mutation listeners to a document profoundly degrades the performance of further DOM modifications to that document (making them 1.5 - 7 times slower!)." from: developer.mozilla.org/en/DOM/Mutation_events
  • Matt Wonlaw
    Matt Wonlaw almost 12 years
    There are numerous problems with this answer. I'd suggest using the approach outlined by @mtkopone below. stackoverflow.com/a/10172676/216941
  • Micah Alcorn
    Micah Alcorn over 11 years
    Love this, although nodeName is rarely useful for me. I just use e.target.className or if ($(e.target).hasClass('my-class')) { ....
  • Pebbl
    Pebbl over 11 years
    +1 had managed to completely miss these special events till now, darn useful! One thing to state having just implemented the above, it would be best to change o.handler() to o.handler.apply(this,arguments) otherwise the event and data objects don't get passed through the event listener.
  • Bron Davies
    Bron Davies over 11 years
    Nice answer, but still that only works for jQuery methods. If you are integrating with another platform that can "pull the rug out" from under you - Adam's answer makes the most sense.
  • Eat at Joes
    Eat at Joes over 11 years
    agreed, this is the best solution to the question.
  • djjeck
    djjeck over 11 years
    This doesn't work when you remove elements without jQuery, though.
  • Charon ME
    Charon ME over 11 years
    this doesn't work a) when elements are detached instead of removed or b) when some old non-jquery libraries use innerHTML to destroy your elements (similar to what djjeck said)
  • Pierre
    Pierre over 11 years
    Beware that handler is called when you $('.thing').unbind('destroyed') which could really be annoying (since unbind means we do not want the handler to be called...)
  • Andy Fleming
    Andy Fleming about 11 years
    @Pierre - Is there a fix for that?
  • mtkopone
    mtkopone about 11 years
    Pierre and @DesignerGuy: added an addendum to the original answer for handling the case where you don't want a callback when unbinding the handler
  • Neil
    Neil almost 11 years
    This was very helpful. I learned that this functionality is within the "Widget" component of jQuery UI if you aren't looking to download the whole UI library.
  • Pierre
    Pierre almost 11 years
    I downvoted because the question asked explicitly for .remove() use, not detach. detach is used especially to not trigger cleanup since the element is probably planned to be reattached later. b) is still true and has yet no reliable handling, at least since DOM mutation events be implemented widely.
  • Charon ME
    Charon ME almost 11 years
    I bet you did this just to get the "critic" badge ;)
  • josh
    josh almost 11 years
    Is this documented anywhere? I just looked through the jQuery UI widget documentation and couldn't find a mention of this. Would like to see whether this is officially supported / any caveats about using it...
  • Marcin
    Marcin over 10 years
    This one doesn't work - tried in jQuery 1.10.2, however the answer below by @mtkopone works perfectly therefore I would vote for updating the answer in that question
  • Carl Smith
    Carl Smith over 10 years
    This one only partly works. If you do remove on the element it fires, but if the element is destroyed some other way, by being overwritten say, it doesn't work.
  • Philipp Munin
    Philipp Munin over 10 years
    You might be right, probably there is other event name for this case. It would be great if you can provide jsfiddle sample for your case.
  • Bill Johnston
    Bill Johnston almost 10 years
    o.type seems to be returning 'destroyed' every time so if (o.handler && o.type !== 'destroyed') isn't working. Any other ways to stop the callback when calling .off? The o object seems to be exactly the same for a removal from the DOM and .off jsfiddle.net/billjohnston4/wg4ks/3
  • Bill Johnston
    Bill Johnston almost 10 years
    @mtkopone yeah, I answered with a workaround here
  • EricP
    EricP over 9 years
    DOMNodeRemovedFromDocument seems to not be supported in Firefox. Perhaps try MutationObserver instead?
  • Eric Holmes
    Eric Holmes about 9 years
    Great special event. Any way to make it usable with $('body').on('destroy', '.target', func) rather than $('.target'.).on('destroy', func) ??
  • jdhildeb
    jdhildeb over 8 years
    mtkopone's solution below works well and does not require jquery UI.
  • user2700551
    user2700551 over 8 years
    Just a precision, the alert will be triggered right before the div is removed. This listener is called right before the action, so keep in mind that the div is still referenced in the DOM at this time. I had a case when I removed a line from a table and needed to update the display (line number), but it is not working because of that.
  • Xdg
    Xdg about 8 years
    This is not working on element itself, only its children.
  • Vladislav Rastrusny
    Vladislav Rastrusny over 7 years
    What about browser compatibility here? Does it still work?
  • Buzogany Laszlo
    Buzogany Laszlo over 7 years
    Is it possible to do it as live event? I need this, but not working: $('body').on('remove', '.selector', function() { ... });
  • Legends
    Legends about 7 years
    The remove event is also triggered when content is removed using html(), at least with jQuery 3.1
  • Legends
    Legends about 7 years
    This even works with .html(""). @BuzoganyLaszlo try document instead of body
  • Kir Mazur
    Kir Mazur about 7 years
    Amazing answer! Really helped me!
  • Kamafeather
    Kamafeather almost 7 years
    It would be great to be free to do that. Unfortunately it is not reliable, as the mutation-events are being deprecated: developer.mozilla.org/en-US/docs/Web/Guide/Events/…
  • Qian Chen
    Qian Chen about 6 years
    I don't understand why the Addendum would work. The o.type==='destroyed' should always be true, no matter through off(), unbind(), or remove(), isn't it? I mean if you modify the if statement according to the addendum, when the element is remove()d, the destroyed callback will not be fired since the whole thing is utilizing the side effect that when an element got remove()d, all its events get unbound.
  • CertainPerformance
    CertainPerformance about 5 years
    It may be slow and a bad idea for code in production, but this is looks like the only method that works synchronously (unlike MutationObserver) and for any node (not just nodes removed via jQuery). This is a great option for debugging.
  • Backo
    Backo about 5 years
    @CarlSmith and @PhilippMunin, what is the event name e.g. when using jQuery replaceWith?
  • Sam
    Sam almost 4 years
    I like this method, the only problem is that I want to trigger removed event using $(e.target).trigger('remove'), but the event never trigger :(
  • ZalemCitizen
    ZalemCitizen over 2 years
    As Kamafeather comment it here below, MutationEvents should not be used : developer.mozilla.org/en-US/docs/Web/API/…
  • Den Pat
    Den Pat over 2 years
    @ZalemCitizen yes, it should not be used but please show other alternatives. also even it says deprecated, it still works for most browsers.
  • Aaron Digulla
    Aaron Digulla over 2 years