5

I have an empty div element:

<div class="message"></div>

At certain point of the webpage, a p tag is dynamically added to the div:

<div class="message">
  <p>Some Message</p>
</div>

The p can get removed, then added again and so.

What event should I use to listen if the div.message has a p child and execute some code?

I found this question, but it involves external plugins.

Isn't there an easy way to accomplish this?

Community
  • 1
  • 1
jviotti
  • 17,881
  • 26
  • 89
  • 148
  • 3
    How is this element added and removed? – Blender Dec 22 '12 at 12:10
  • Via jquery.validation plugin. I could insert the code from there but I'm looking for another solution keeping that code untouched – jviotti Dec 22 '12 at 12:12
  • I would be surprised if the plugin doesn't have some configurable callbacks that run before that element is created. Here's an example: http://stackoverflow.com/questions/2762458/customising-event-delegates-in-the-jquery-validation-plug-in. `highlight` looks promising. – Blender Dec 22 '12 at 12:17

2 Answers2

10

Depending on your implementation and how fast you need to recognize a change, you might be able to get away with using a setInterval to periodically monitor the contents of a certain element.

var checkContents = setInterval(function(){
  if ($("div.message p").length > 0){ // Check if element has been found
    // There is a <p> element in here!!
    console.log($("div.message p").length());
  }
},1000);

The previous snippet will check for <p> elements within div.message elements every second (1000 milliseconds), and if present will log the number of them to the console.


Depending on your browser support requirements, you could alternatively use mutation events -

Mutation events provide a mechanism for a web page or an extension to get notified about changes made to the DOM...

var element = document.querySelectorAll('div.message')
element.addEventListener("DOMNodeInserted", function (ev) {
  // ...
}, false);
lukyer
  • 7,595
  • 3
  • 37
  • 31
Lix
  • 47,311
  • 12
  • 103
  • 131
  • 1
    Mutation events are now superceded by Mutation Observers – Peter P. Oct 09 '15 at 00:19
  • https://developer.mozilla.org/en-US/docs/Web/API/MutationEvent it is deprecated. – fuat Dec 19 '21 at 10:00
  • Quite surprised this is the top answer, Can someone comment on the effects on the page of constantly (once per second) checking if this element exists? I don't really like "polling" like this but it's a quick easy fix until I can implement something better which I feel would perform better such. as the mutation observer. – SwimmingG Dec 27 '21 at 15:20
  • 1
    @SwimmingG - not 100% how relevant this answer is 9yrs later. Having a 1 second poll shouldn't have a massive effect on the page but this depends what else is happening on the page. I wouldn't recommend using this same method to detect multiple changes - creating too many simultaneous setIntervals probably will have a negative effect on any other JS that is being run at the same time. [Mutation observers](https://caniuse.com/mutationobserver) might be a better choice depending on your browser support. – Lix Dec 27 '21 at 15:53
  • @Lix thanks I'll check them out :) – SwimmingG Dec 28 '21 at 19:47
1

Vanilla JS has an awesome way to detect any DOM changes (including if a node adds any child nodes), check out: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

But these docs aren't super clear so here's a quick explanation.

First, you want to have a target node to listen to:

const targetNode = document.getElementById('some-id');

Then you want to create a trigger when the target changes (called MutationObserver):

const observer = new MutationObserver(callbackFunction);

Define what you want to happen when the target changes:

const callbackFunction = function(mutationsList) { // Use traditional 'for loops' for IE 11 for(const mutation of mutationsList) { if (mutation.type === 'childList') { console.log('A child node has been added or removed.'); } else if (mutation.type === 'attributes') { console.log('The ' + mutation.attributeName + ' attribute was modified.'); } } };

note: mutationsList is an object with loads of information what the targetNode has changed including style, addedNodes, etc...

Finally, you can start observing the target node for mutations (changes) with:

observer.observe(targetNode, { childlist: true, attributes: true });

The second parameter is an 'options' object to define what type of mutation (changes) you're looking for.

Hopefully that helps, I've found it to be a really powerful and underrated tool in js

sj.coded
  • 21
  • 2
  • This is great. Using MutationObserver with this --> `document.contains(myElement)` within the `MutationObserver` was the best route for my build. See also this link. Also no JQuery. https://stackoverflow.com/questions/20420577/detect-added-element-to-dom-with-mutation-observer – Code Novice Feb 18 '23 at 19:08