2

I have a div class ".square", i want to show an alert if there is a mouse clicking outside of the div element, i can't find something similar according to mouse event on this website w3schools. ( i want the opposite of my actual code ) Thank you.

function myFunction() {
  alert('hi')
}
.square{
width: 100px;
height: 100px;
background-color: red;
}
<div class="square" onclick="myFunction()" ></div>
alioua walid
  • 247
  • 3
  • 19

3 Answers3

4

Simple solution: Add a listener to the window that produces the alert and add a listener to the div that stops the click event from propagating so that it never reaches the window.

Disclaimer: calling stopPropagation is not a great thing to do as it's quite intrusive, but I'm guessing you're just trying things out, so it should be fine.

window.onclick = () => alert('hi')
.square{
  width: 100px;
  height: 100px;
  color: red;
  background-color: teal;
}
<div onclick="event.stopPropagation()" class="square">TEST</div>

Here's a good answer that describes a more proper way to achieve this.

And here's that answer adjusted to your case in a more correct solution where we look at the click event to determine if we should call alert:

const outsideClickListener = element => ({ target }) => {
  if (!element.contains(target)) {
    alert("hi");
  }
};

const squareEl = document.getElementById("square");
document.addEventListener("click", outsideClickListener(squareEl));
#square{
  width: 100px;
  height: 100px;
  color: red;
  background-color: teal;
}
<div id="square">TEST</div>

Why should we not use stopPropagation? In a small project there's not a big problem to use it (which is why it's my top recommendation). But in a big real world project it's ill advice, because it can break behavior of other stuff. See below example. Developer A added Test 1 and expects alert('hi 1') to be ran every time the user clicks outside of Test 1. But developer B added Test 2 which calls stopPropagation that stops all events, so when the user clicks Test 2 (which is outside of Test 1) alert('hi 1') is not ran and we have a bug.

window.onclick = () => alert('hi 2')

const outsideClickListener = element => ({ target }) => {
  if (!element.contains(target)) {
    alert("hi 1");
  }
};

const squareEl = document.getElementsByClassName("square")[0];
document.addEventListener("click", outsideClickListener(squareEl));
.square, .circle {
  width: 100px;
  height: 100px;
  color: red;
  background-color: teal;
}

.square {
  background-color: teal;
}

.circle {
  background-color: wheat;
}
<div class="square">TEST 1</div>
<div onclick="event.stopPropagation()" class="circle">TEST 2</div>
Mohrn
  • 816
  • 4
  • 15
  • Thank you for your answer, but i didn't understund what you meant by "stopPropagation is not a great thing to do as it's quite intrusive" can you please explain ? – alioua walid Aug 10 '19 at 17:35
  • 1
    There you go, I hope it makes sense :) – Mohrn Aug 10 '19 at 17:47
  • 1
    Yes now i get it, it can create confusion between elements, i'm willing to use it as an exit on a popup if you click outside it, so i'll take your second answer, thank you very much sir, very appreciated. – alioua walid Aug 10 '19 at 18:00
1
<div class="square">squre</div>
.square{
  width:200px;
  height:200px;
  border:1px solid red;
}



let sq = document.querySelector('.square');
window.addEventListener('click', function(e){  
    if (sq.contains(e.target)){
       alert('inside square box')
    } else{
       alert('outside square box')
      }
 });    
ravi
  • 1,127
  • 9
  • 10
1

Make a click event listener for the body.

If the body is clicked check if the target is the square, or if the target is a child of the square

function myFunction() {
  alert('hi');
}
$(document).ready(function(){
$('body').on('click', function(e) {
  if($(e.target).is('.square') || $(e.target).closest('.square').length) {
    myFunction();

  }
});
});
.square{
width: 100px;
height: 100px;
color: red;
background:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class="square">
</div>
<body>
RainyRain
  • 305
  • 2
  • 10