Подтвердить что ты не робот

Обнаруживать элемент внешнего элемента (ванильный JavaScript)

Я искал хорошее решение во всем мире, но я не могу найти тот, который не использует jQuery.

Есть ли кросс-браузер, обычный способ (без странных хаков или легко сломать код), чтобы обнаружить щелчок за пределами элемента (который может содержать или не иметь детей)?

4b9b3361

Ответ 1

Добавьте прослушиватель событий в document и используйте Node.contains(), чтобы узнать, является ли цель события (которая является самой верхней элемент щелкнул) находится внутри указанного элемента. Он работает даже в IE5

var specifiedElement = document.getElementById('a');

//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
  var isClickInside = specifiedElement.contains(event.target);

  if (!isClickInside) {
    //the click was outside the specifiedElement, do something
  }
});

var specifiedElement = document.getElementById('a');

//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
  var isClickInside = specifiedElement.contains(event.target);
  if (isClickInside) {
    alert('You clicked inside A')
  } else {
    alert('You clicked outside A')
  }
});
div {
  margin: auto;
  padding: 1em;
  max-width: 6em;
  background: rgba(0, 0, 0, .2);
  text-align: center;
}
Is the click inside A or outside?
<div id="a">A
  <div id="b">B
    <div id="c">C</div>
  </div>
</div>

Ответ 2

Вам нужно обработать событие click на уровне документа. В объекте события у вас есть свойство target, самый внутренний элемент DOM, который был нажат. С этим вы проверяете себя и подходите к родителям до элемента документа, если один из них является вашим наблюдаемым элементом.

См. пример в 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";
      return;
    }
    level++;
  }
  document.getElementById("out").innerHTML = "not x clicked";
});

Как всегда, это не совместимо с перекрестным браузером из-за addEventListener/attachEvent, но оно работает следующим образом.

Нажимается дочерний элемент, если не event.target, но один из его родителей является наблюдаемым элементом (я просто подсчитываю уровень для этого). У вас может также быть boolean var, если элемент найден или нет, чтобы не возвращать обработчик из предложения for. Мой пример ограничивает то, что обработчик заканчивается только тогда, когда ничего не соответствует.

Добавляя совместимость между браузерами, я обычно делаю это так:

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 в IE, как элемент, как jQuery для обработчиков событий. Есть много аргументов, чтобы иметь в виду несколько бит jQuery;)

Ответ 3

Как насчет этого:

JSBBIN-Demo

document.onclick = function(event){
  var hasParent = false;
    for(var node = event.target; node != document.body; node = node.parentNode)
    {
      if(node.id == 'div1'){
        hasParent = true;
        break;
      }
    }
  if(hasParent)
    alert('inside');
  else
    alert('outside');
} 

Ответ 4

Чтобы скрыть элемент за кликом за его пределами, я обычно применяю такой простой код:

var bodyTag = document.getElementsByTagName('body');
var element = document.getElementById('element'); 
function clickedOrNot(e) {
	if (e.target !== element) {
		// action in the case of click outside 
		bodyTag[0].removeEventListener('click', clickedOrNot, true);
	}	
}
bodyTag[0].addEventListener('click', clickedOrNot, true);