If you want to implement some logic when a user clicks outside of an element (e.g. closing a dropdown), the most use solution is to add a click listener on both the document and the element and prevent propagation in the click handler of the element e.g.:
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(document).on('click', function(event) {
alert("outside");
});
$(document).ready(function() {
$('#div3').on('click', function() {
return false;
});
});
</script>
</head>
<body>
<div style="background-color:blue;width:100px;height:100px;" id="div1"></div>
<div style="background-color:red;width:100px;height:100px;" id="div2"></div>
<div style="background-color:green;width:100px;height:100px;" id="div3"></div>
<div style="background-color:yellow;width:100px;height:100px;" id="div4"></div>
<div style="background-color:grey;width:100px;height:100px;" id="div5"></div>
</body>
</html>
If you use other libraries with add their own click handlers, it might break some of the functionality when stopping event propagation (see this article for more info). In order to implement this functionality in a way which doesn’t mess with the event propagation, you only need a click handler on the document and check whether the click target is the element or one of its children e.g. using the jQuery function closest:
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
$(document).on('click', function(event) {
if (!$(event.target).closest('#div3').length) {
alert("outside");
}
});
</script>
</head>
<body>
<div style="background-color:blue;width:100px;height:100px;" id="div1"></div>
<div style="background-color:red;width:100px;height:100px;" id="div2"></div>
<div style="background-color:green;width:100px;height:100px;" id="div3"></div>
<div style="background-color:yellow;width:100px;height:100px;" id="div4"></div>
<div style="background-color:grey;width:100px;height:100px;" id="div5"></div>
</body>
</html>
If you want to avoid jQuery and implement it in a pure JavaScript way with no additional dependencies, you can use addEventListener to had an event handler on the document and implement your own function to replace closest e.g.:
<html>
<head>
<script>
function findClosest (element, fn) {
if (!element) return undefined;
return fn(element) ? element : findClosest(element.parentElement, fn);
}
document.addEventListener("click", function(event) {
var target = findClosest(event.target, function(el) {
return el.id == 'div3'
});
if (!target) {
alert("outside");
}
}, false);
</script>
</head>
<body>
<div style="background-color:blue;width:100px;height:100px;" id="div1"></div>
<div style="background-color:red;width:100px;height:100px;" id="div2"></div>
<div style="background-color:green;width:100px;height:100px;" id="div3">
<div style="background-color:pink;width:50px;height:50px;" id="div6"></div>
</div>
<div style="background-color:yellow;width:100px;height:100px;" id="div4"></div>
<div style="background-color:grey;width:100px;height:100px;" id="div5"></div>
</body>
</html>
The findClosest function just checks whether the provided function returns true when applied to the element and if not recursively calls itself with the parent of the element as parameter until there no parent.
If instead of using the element id, you want to apply this to all elements having a given class, you can use this function as second argument when calling findClosest:
function(el) {
return (" " + el.className + " ").replace(/[\n\t\r]/g, " ").indexOf(" someClass ") > -1
}