Tiberiu-Ionuț Stan Tiberiu-Ionuț Stan - 1 year ago 175
Javascript Question

Detect click outside element (vanilla JavaScript)

I have searched for a good solution everywhere, yet I can't find one which does not use jQuery.

Is there a cross-browser, normal way (without weird hacks or easy to break code), to detect a click outside of an element (which may or may not have children)?

Answer Source

You need to handle the click event on document level. In the event object, you have a target property, the inner-most DOM element that was clicked. With this you check itself and walk up its parents until the document element, if one of them is your watched element.

See the example on jsFiddle

document.addEventListener("click", function (e) {
  var level = 0;
  for (var element = e.target; element; element = element.parentNode) {
    if (element.id === 'x') {
      document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked";
  document.getElementById("out").innerHTML = "not x clicked";

As always, this isn't cross-bad-browser compatible because of addEventListener/attachEvent, but it works like this.

A child is clicked, when not event.target, but one of it's parents is the watched element (i'm simply counting level for this). You may also have a boolean var, if the element is found or not, to not return the handler from inside the for clause. My example is limiting to that the handler only finishes, when nothing matches.

Adding cross-browser compatability, I'm usually doing it like this:

var addEvent = function (element, eventName, fn, useCapture) {
  if (element.addEventListener) {
    element.addEventListener(eventName, fn, useCapture);
  else if (element.attachEvent) {
    element.attachEvent(eventName, function (e) {
      fn.apply(element, arguments);
    }, useCapture);

This is cross-browser compatible code for attaching an event listener/handler, inclusive rewriting this in IE, to be the element, as like jQuery does for its event handlers. There are plenty of arguments to have some bits of jQuery in mind ;)