jQuery-événement déclencheur lorsqu'un élément est retiré du DOM

j'essaie de comprendre comment exécuter un code js quand un élément est supprimé de la page:

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

y a-t-il un événement adapté pour cela, quelque chose comme:

jQuery('#some-element').onremoval( function() {
    // do post-mortem stuff here
});

merci.

190
demandé sur sa125 2010-02-04 17:46:04

14 réponses

vient de vérifier, il est déjà intégré dans la version actuelle de JQuery:

jQuery-v1.9.1

jQuery UI-v1.10.2

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

Important : c'est la fonctionnalité de jQuery UI script (pas JQuery), donc vous devez charger les deux scripts (jquery et jQuery-ui) pour le faire fonctionner. Voici un exemple: http://jsfiddle.net/72RTz /

105
répondu Philipp Munin 2013-10-20 01:13:12

Vous pouvez utiliser jQuery événements spéciaux pour cela.

en toute simplicité,

Installation:

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

Utilisation:

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

Addendum pour répondre aux commentaires de Pierre et DesignerGuy:

pour ne pas avoir le feu de rappel lors de l'appel $('.thing').off('destroyed') , changer la condition if en: if (o.handler && o.type !== 'destroyed') { ... }

188
répondu mtkopone 2013-02-06 09:38:16

vous pouvez vous lier à L'événement DOMNodeRemoved (partie de DOM Level 3 WC3 spec).

fonctionne dans IE9, dernières versions de Firefox et Chrome.

exemple:

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

vous pouvez également obtenir une notification lorsque des éléments sont insérés en liant à DOMNodeInserted

43
répondu Adam 2011-08-08 19:27:33

il n'y a pas d'événement intégré pour supprimer des éléments, mais vous pouvez en créer un par la méthode de suppression par défaut de fake-extending jQuery. Notez que le callback doit être appelé avant de le supprimer pour conserver la référence.

(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: certains problèmes avec cette réponse ont été soulignés par d'autres affiches.

  1. cela ne fonctionnera pas lorsque le noeud est enlevé via html() replace() ou autre jQuery les méthodes de
  2. Cet événement bulles
  3. jQuery UI remplace supprimer ainsi

la solution la plus élégante à ce problème semble être: https://stackoverflow.com/a/10172676/216941

37
répondu David 2017-05-23 11:47:22

Hooking .remove() n'est pas la meilleure façon de gérer cela car il existe de nombreuses façons de supprimer des éléments de la page (par exemple en utilisant .html() , .replace() , etc).

afin de prévenir divers risques de fuite de mémoire, jQuery interne va essayer d'appeler la fonction jQuery.cleanData() pour chaque élément enlevé, indépendamment du méthode utilisée pour l'enlever.

voir cette réponse pour plus de détails: fuites de mémoire javascript

donc, pour de meilleurs résultats, vous devriez accrocher la fonction cleanData , qui est exactement ce que le jquery.événement.détruit plugin n':

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

32
répondu zah 2017-05-23 11:47:22

pour ceux qui utilisent jQuery UI:

jQuery UI a dépassé certaines des méthodes jQuery pour implémenter un événement remove qui est manipulé non seulement quand vous supprimez explicitement l'élément donné, mais aussi si l'élément est enlevé du DOM par n'importe quelle méthode jQuery auto-nettoyante (par exemple replace , html , etc.). Cela vous permet essentiellement de mettre un crochet dans les mêmes événements qui sont tirés lorsque jQuery "nettoie" les événements et les données associés avec un élément du DOM.

John Resig a indiqué qu'il est ouvert à l'idée de mettre en œuvre cet événement dans une future version de jQuery core, mais je ne sais pas où il se trouve actuellement.

6
répondu StriplingWarrior 2011-09-28 19:04:56

je ne pouvais pas obtenir cette réponse de travailler avec la déliaison (malgré la mise à jour voir ici ), mais a été en mesure de trouver un moyen de contourner cela. La réponse était de créer un événement spécial' destroy_proxy 'qui déclenchait un événement' détruit'. Vous mettez l'écouteur d'événement à la fois sur 'destroyed_proxy' et 'destroyed', puis quand vous voulez défaire, vous déboulez simplement l'événement 'destroyed':

var count = 1;
(function ($) {
    $.event.special.destroyed_proxy = {
        remove: function (o) {
            $(this).trigger('destroyed');
        }
    }
})(jQuery)

$('.remove').on('click', function () {
    $(this).parent().remove();
});

$('li').on('destroyed_proxy destroyed', function () {
    console.log('Element removed');
    if (count > 2) {
        $('li').off('destroyed');
        console.log('unbinded');
    }
    count++;
});

voici un violon

4
répondu Bill Johnston 2017-05-23 12:34:41

Solution sans utilisation de jQuery UI

( j'ai extrait cette extension du cadre jQuery UI )

fonctionne avec: empty() et html() et remove()

$.cleanData = ( function( orig ) {
    return function( elems ) {
        var events, elem, i;
        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
            try {

                // Only trigger remove when necessary to save time
                events = $._data( elem, "events" );
                if ( events && events.remove ) {
                    $( elem ).triggerHandler( "remove" );
                }

            // Http://bugs.jquery.com/ticket/8235
            } catch ( e ) {}
        }
        orig( elems );
    };
} )( $.cleanData );

avec cette solution vous pouvez aussi débiter le gestionnaire d'événements.

$("YourElemSelector").off("remove");

essayez! - Exemple

$.cleanData = (function(orig) {
  return function(elems) {
    var events, elem, i;
    for (i = 0;
      (elem = elems[i]) != null; i++) {
      try {

        // Only trigger remove when necessary to save time
        events = $._data(elem, "events");
        if (events && events.remove) {
          $(elem).triggerHandler("remove");
        }

        // Http://bugs.jquery.com/ticket/8235
      } catch (e) {}
    }
    orig(elems);
  };
})($.cleanData);


$("#DivToBeRemoved").on("remove", function() {
  console.log("div was removed event fired");
});

$("p").on("remove", function() {
  console.log("p was removed event fired");
});

$("span").on("remove", function() {
  console.log("span was removed event fired");
});

// $("span").off("remove");

$("#DivToBeRemoved").on("click", function() {
  console.log("Div was clicked");
});

function RemoveDiv() {
  //       $("#DivToBeRemoved").parent().html("");    
  $("#DivToBeRemoved").remove();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>OnRemove event handler attached to elements `div`, `p` and `span`.</h3>
<div class="container">
  <br>
  <button onclick="RemoveDiv();">Click here to remove div below</button>
  <div id="DivToBeRemoved">
    DIV TO BE REMOVED 
    contains 1 p element 
    which in turn contains a span element
    <p>i am p (within div)
      <br><br><span>i am span (within div)</span></p>
  </div>
</div>

Supplémentaires Démo - jsBin

4
répondu Legends 2018-06-29 09:44:25

j'aime la réponse de mtkopone en utilisant les événements spéciaux jQuery, mais notez qu'elle ne fonctionne pas a) quand les éléments sont détachés au lieu d'être enlevés ou b )quand certaines vieilles bibliothèques non-jquery utilisent innerHTML pour détruire vos éléments

3
répondu Charon ME 2012-12-11 12:39:31

Je ne suis pas sûr qu'il y ait une poignée d'événement pour cela, donc vous devriez garder une copie du DOM et comparer avec le DOM existant dans une sorte de boucle de sondage - ce qui pourrait être assez désagréable. Firebug fait cela cependant - si vous inspectez le HTML et exécutez quelques modifications DOM -, il met en évidence les changements en jaune dans la console Firebug pour un court moment.

alternativement, vous pouvez créer une fonction Supprimer...

var removeElements = function(selector) {
    var elems = jQuery(selector);

    // Your code to notify the removal of the element here...
    alert(elems.length + " elements removed");

    jQuery(selector).remove();
};

// Sample usage
removeElements("#some-element");
removeElements("p");
removeElements(".myclass");
1
répondu user75525 2010-02-04 14:52:27

comment créer un jQuery live remove listener :

$(document).on('DOMNodeRemoved', function(e)
{
  var $element = $(e.target).find('.element');
  if ($element.length)
  {
    // do anything with $element
  }
});

ou:

$(document).on('DOMNodeRemoved', function(e)
{
  $(e.target).find('.element').each(function()
  {
    // do anything with $(this)
  }
});
1
répondu Buzogany Laszlo 2017-02-15 07:58:37

en référence à la réponse de @David:

quand vous voulez faire soo avec une autre fonction, par exemple. html() comme dans mon cas, n'oubliez pas d'ajouter le retour en nouvelle fonction:

(function() {
    var ev = new $.Event('html'),
        orig = $.fn.html;
    $.fn.html = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();
0
répondu Patryk M 2012-01-25 14:56:03

This.

$.each(
  $('#some-element'), 
        function(i, item){
            item.addEventListener('DOMNodeRemovedFromDocument',
                function(e){ console.log('I has been removed'); console.log(e);
                })
         })
0
répondu Matas Vaitkevicius 2014-03-26 15:25:57

l'événement "Supprimer" de jQuery fonctionne très bien, sans ajout. Il pourrait être plus fiable à temps d'utiliser un truc simple, au lieu de corriger jQuery.

il suffit de modifier ou d'ajouter un attribut dans l'élément que vous êtes sur le point de supprimer du DOM. Ainsi, vous pouvez déclencher n'importe quelle fonction de mise à jour, qui ignorera simplement les éléments en cours de destruction, avec l'attribut "do_not_count_it".

supposons que nous ayons un tableau avec des cellules correspondant aux prix, et que vous devez montrer seulement le dernier prix: C'est le sélecteur à déclencher quand une cellule de prix est supprimée (nous avons un bouton dans chaque ligne de la table faisant cela, non montré ici)

$('td[validity="count_it"]').on("remove", function () {
    $(this).attr("validity","do_not_count_it");
    update_prices();
});

et voici une fonction qui trouve le dernier prix dans le tableau, sans tenir compte du dernier, si c'est celui qui a été supprimé. En effet, lors de la "suppression" de l'événement est déclenché, et lorsque cette fonction est appelée, l'élément n'est pas supprimé encore.

function update_prices(){
      var mytable=$("#pricestable");
      var lastpricecell = mytable.find('td[validity="count_it"]').last();
}

à la fin, la fonction update_prices() fonctionne très bien, et après cela, L'élément DOM est supprimé.

0
répondu philippe 2018-07-01 09:36:36