JavaScript: don’t remove element before all events occurs

Sometimes really simple bug can be very hard to find – and expensive to have. In this case I’m talking about business costs – a lot of some specific events for a marketing campaign wasn’t tracked properly.

The Problem

Tracking of “clicked” events doesn’t work for some buttons (mostly responsible for closing modals/alerts).

The Context

Old code, jQuery, a lot of modules compiled by gulp. But simplified code can be presented like this.

First we have really clear html structure:


<div class="alert">
  Some message
  <button class="btn close" data-tracking="foo">close</button>
</div>

And JavaScript code to closing/removing modal and tracking part:


jQuery(($) => {
  var $alert = $('.alert');
  var $close = $alert.find('.close');

  // close alert (clear html)
  $close.click(() => {
    console.log($close.data('tracking')); // will work
    $alert.html('').hide(); // button removed
  });

  // some other tracking library
  $('body').on('click', '.alert > .btn', (e) => {
    console.log($(e.target).data('tracking')); // won't work !!!
  });
});

The Reason:

DOM element removed in first method will cause second one to fail (selector .alert > .btn cannot find anything).

The Quick Fix:

Simple setTimeout will do the trick – just delay removing of the element.
You can also hide it without removing it.