2

As the question states, what I'm attempting to do is have a function that is called when a DOM element is removed from the DOM, much like a destructor.

I looked into unload, but from my understanding that's only called when the browser navigates away from the page.

Thanks in advance!

mrh89
  • 89
  • 10
  • How exactly do you remove the DOM element? – Aleksandar Trajkov Oct 07 '11 at 10:19
  • Ah yes, probably should've shown that: `$('#loadingBlock').remove();` – mrh89 Oct 07 '11 at 10:30
  • Sorry for the multiple edits- I'm new to formatting :/ – mrh89 Oct 07 '11 at 10:31
  • 1
    I think this was already done: [stackoverflow.com - jquery-bindremove](http://stackoverflow.com/questions/3432944/jquery-bindremove) – Mark Oct 07 '11 at 10:36
  • Thanks @Mark, that's sort of what I'm looking for, but is it possible to have a reference to what the object that has been removed is? I have a main DOM element that is the 'parent' to all the other child elements I'm concerned with, binding "DOMNodeRemoved" does fire every time an element is removed, but I need a reference to do allow me to call each child's individual destruction code... – mrh89 Oct 07 '11 at 10:57
  • For the record, jQuery UI implements the remove event (in a fashion similar to the answer here: http://stackoverflow.com/a/7686327/1329367) – Mahn Feb 21 '13 at 12:49

4 Answers4

2

It is possible to use the special events to build removal tracking. I've created an example that allows to bind to an removed event. Note that this approach only works when the removal is initiated by jQuery (calling $(…).remove()) for example. For a more general solution use DOMNodeRemoved but that wouldn't work in IE.

To enable tracking for an element call $(…).trackRemoval() and the element will fire a removed event when you remove it or one of its parents.

// Create a scope so that our variables are not global
(function(){
    /**
     * True while unbinding removal tracking
     */
    var isUntracking = false;

    /**
     * A reference that is only known here that nobody else can play with our special event.
     */
    var dummy = function(){};

    /**
     * Special event to track removals. This could have any name but is invoked during jQuery's cleanup on removal to detach event handlers.
     */
    jQuery.event.special.elementRemoved = {
        remove: function(o){
            if(o.handler===dummy && !isUntracking){
                $(this).trigger('removed');
            }
        }
    };

    /**
     * Starts removal tracking on an element
     */
    jQuery.fn.trackRemoval = function(){
        this.bind('elementRemoved', dummy);
    };

    /**
     * Stops removal tracking on an element
     */
    jQuery.fn.untrackRemoval = function(){
        isUntracking = true;
        this.unbind('elementRemoved', dummy);
        isUntracking = false;
    };
})();

The jsFiddle contains sample code for usage.

Augustus Kling
  • 3,303
  • 1
  • 22
  • 25
1

I don't know if it's that what you're looking for. Not really pretty code, just to show what I would like to use:

// Just for this script's sake, you'll want to do it differently
var body = $("body");
var element = $('#loadingBlock');

// Bind the "destructor" firing event
body.bind("elementDeleted", function (element) {
  // your "destructor" code
});

// Trigger the event, delete element, can be placed in a function, overloaded, etc.
body.trigger("elementDeleted", element);
element.remove();

There are of course solutions based on watching the DOM directly but the problem is the browser compatibility. You should probably check out mutation events.

Przemek
  • 6,300
  • 12
  • 44
  • 61
  • Thanks, I was aware it's possible to do this, but I'm hoping to manage each of the elements dynamically. – mrh89 Oct 07 '11 at 11:00
  • You can achieve it by overloading the default remove method [like this](http://stackoverflow.com/questions/2539011/jquery-core-method-overload) to fire a custom event when called or sacrifice cross-browser compatibility and use mutation events. – Przemek Oct 07 '11 at 11:08
  • I ended up deciding that overriding the default event was a little more work than is really required right now, so I've gone with what you originally answered. Thanks! – mrh89 Oct 07 '11 at 14:19
  • how is this a useful answer if you have to remember to _manually_ trigger the event yourself immediately before calling `.remove` ? – Alnitak Oct 07 '11 at 20:53
  • you might as well just have called `callback_func(element)` instead of using a trigger. – Alnitak Oct 07 '11 at 21:00
1

Try this:

(function($) {
    var _remove = $.fn.remove;
    $.fn.remove = function() {
        this.trigger('remove');             // notify removal
        return _remove.apply(this, arguments); // call original
    };
})(jQuery);

usage:

$(element).bind('remove', callback);
...
// some time later
$(element).remove();

See a working example at http://jsfiddle.net/alnitak/25Pnn/

Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

You could always Overload the Remove function (all javascript objects can be dynamically changes in runtime) and replace it with your own function that triggers an event you can use to react to remove.

David Mårtensson
  • 7,550
  • 4
  • 31
  • 47