JavaScript Document Mutation Events

Sometimes you get a situation where you need to know when a new element has been added to the page with JavaScript. A common example of this is adding event listeners to a certain type of input then adding more of those inputs - the new ones do not get the event. For a simple example it's obviously easier just to add the event handler when adding the new input so let's assume we're talking about something more complex. There used to be an event for this kind of thing

element.addEventListener('DOMNodeInserted', function (event){
  /* do stuff */
});

but it was removed for being a huge performance killer.

Before we get on to the workaround here's a quick example illustrating the problem

See the Pen yNpzQX.

The inputs that are on the page when it loads get the nice picker but any new ones that get added do not.

We can use the animationstart event to detect when an animation begins, so by using a bit of CSS to play an animation on a new element that we want to target we can catch it being added to the page. First we need to target the element we want and add an animation that will be very unlikely to do anything visible, a common one is to use the outline-color property.

.date-picker {
  animation: dateInputAdded 0s;
}

@keyframes dateInputAdded {
  from { outline-color: #fff; }
  to { outline-color: #000; }
}

A script can then handle this animation starting and add the event listeners

document.addEventListener('animationstart', function(event){
  if (event.animationName == 'dateInputAdded'){
    $(event.target).datepicker();
  }
});

If you can get this at the top of the document so it will catch all elements then there is no need to query for existing elements meaning everything is in one place. Lovely.

See the Pen vOpeqo.

Post a new comment