Matthew Cornelisse
Matthew Cornelisse

Reputation: 1043

Detecting DOM item removed in javascript

I am writing a plugin that is given a id. it adds some code to that id and starts some events. the problem I have found is if the container is later overwriten I can't find a way to shut down the events so they don't keep running. Below is a demo script to show what I have tried. I can't seem to find anyway to detect test2 doesn't exist and clear the interval.

$(function() {
				
  /* *********************************
  *  Simple example of something that could be done
  *  being told to work on id test2
  ********************************* */
				
  var a=0;
  $("#test2").append('<br>I Ran');
  var id=setInterval(function() {
    console.log("running");		//ctrl+shift+j will see message every second
  },1000);
					
  //try to remove id test2 is removed
  $(document).on("DOMNodeRemoved", function (e) {
    console.log(e.target.id,e.target);
    if (e.target.id=="test2") { //is never true since test2 was added by jquery
		clearInterval(id);	//stops message from being writen
    }
  })
					
					
  /* *********************************
  *  Some other part of app that wipes away the above script is playing with
  ********************************* */
					
$(document).on('click','#del',function(){
  $("#test").html('wipe out');	//replaces content of div test with test2.html 			
  });
				
});
			
<!DOCTYPE html>
<html lang="en">
  <header> 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  </header>
  <body>
  <div id="test">
  <div id="2" class="test">
    <div id="test2">help</div>
  </div>
  </div>
  <div id="del">Press here to remove</div>
  </body>
</html>

Upvotes: 6

Views: 230

Answers (2)

Dinh Tran
Dinh Tran

Reputation: 614

I can't believe no one has told you this: You're using Mutation Events which is deprecated as described in here.

As recommended in that page, you should use Mutation Observer instead.

Below is the snippet I re-wrote your js code using Mutation Observer based on the original example

$(function () {
    var a = 0;
    $("#test2").append('<br>I Ran');
    var id = setInterval(function () {
        console.log("running");
    }, 1000);
    // select the target node
    var target = document.getElementById("test");
    // create an observer instance
    var observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            if (mutation.removedNodes.length > 0) { // You need to check if the mutation.removedNodes array contains div#test2 here. I'm just too lazy.
                clearInterval(id);	//stops message from being writen
                console.log("stopped!");
                console.log("You can set debugger here to play with mutation.removedNodes array!");
                observer.disconnect(); // stop observing
            }
        });
    });
    // configuration of the observer:
    var config = { childList: true };
    observer.observe(target, config); // start observe
    $(document).on('click', '#del', function () {
        $("#test").html('wipe out');	//replaces content of div test with test2.html 			
    });
});
<!DOCTYPE html>
<html lang="en">
<header>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  <script src="site.js"></script>
</header>

<body>
  <div id="test">
    <div id="2" class="test">
      <div id="test2">help</div>
    </div>
  </div>
  <div id="del">Press here to remove</div>
</body>

</html>

Upvotes: 0

Robert Brisita
Robert Brisita

Reputation: 5844

The problem is that you are removing the parent of test2, so the target is never going to be what you are testing against. To solve this, in your conditional try:

if ($(e.target).find("#test2").length) {
    clearInterval(id);
}

$(function() {
				
  /* *********************************
  *  Simple example of something that could be done
  *  being told to work on id test2
  ********************************* */
				
  var a=0;
  $("#test2").append('<br>I Ran');
  var id=setInterval(function() {
    console.log("running");		//ctrl+shift+j will see message every second
  },1000);
					
  //try to remove id test2 is removed
  $(document).on("DOMNodeRemoved", function (e) {
    console.log(e.target.id,e.target);
    if ($(e.target).find("#test2").length) {
		clearInterval(id);
    }
  })
					
					
  /* *********************************
  *  Some other part of app that wipes away the above script is playing with
  ********************************* */
					
$(document).on('click','#del',function(){
  $("#test").html('wipe out');	//replaces content of div test with test2.html 			
  });
				
});
			
<!DOCTYPE html>
<html lang="en">
  <header> 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
  </header>
  <body>
  <div id="test">
  <div id="2" class="test">
    <div id="test2">help</div>
  </div>
  </div>
  <div id="del">Press here to remove</div>
  </body>
</html>

Upvotes: 1

Related Questions