Display alert if clicking outside div - javascript

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>

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>

<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')
}
});

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>

Related

How to fix the recursion problem in jQuery code

I have been on a game project for a while. I have used bootstrap and jQuery. But to keep it simple, here is what the piece of code in which I did not understand anything looks like. I wanted that by clicking and only clicking on item A, item B will show and disappear after clicking on it. I added an instruction that will show me after every click on an item a message in the console and watch what happens!
let elt_boxOne = $("#bx_one");
let elt_boxTwo = $("#bx_two");
elt_boxTwo.hide();
elt_boxOne.click($.proxy(function() {
elt_boxTwo.show();
elt_boxTwo.click($.proxy(function() {
console.log("Hello world");
elt_boxTwo.hide();
}, this));
}, this));
/*As you can see the first time has no problem but if we try the second time there will be two messages and the third click will show three etc... I mean what the hell is going on???*/
#bx_one {
width: 200px;
height: 50px;
background-color: red;
text-align: center;
font-weight: bold;
}
#bx_two {
width: 200px;
height: 50px;
background-color: orange;
text-align: center;
font-weight: bold;
}
<div id="bx_one">Box one</div>
<div id="bx_two">Box two</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You are initializing the click listener to many times, when you click on button 1. You have to move it outside, independent of the first click handler... like this:
BTW, you don't need proxies, you can use arrow functions if you need the context inside.
let elt_boxOne = $("#bx_one");
let elt_boxTwo = $("#bx_two");
elt_boxTwo.hide();
elt_boxOne.click(() => {
elt_boxTwo.show();
});
elt_boxTwo.click(() => {
console.log("Hello world");
elt_boxTwo.hide();
});
#bx_one {
width: 200px;
height: 50px;
background-color: red;
text-align: center;
font-weight: bold;
}
#bx_two {
width: 200px;
height: 50px;
background-color: orange;
text-align: center;
font-weight: bold;
}
<div id="bx_one">Box one</div>
<div id="bx_two">Box two</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Do not create your "box 2" listener inside of your "box 1" listener. Simply separate the two element's click handlers.
const
$boxOne = $("#bx-one"),
$boxTwo = $("#bx-two").hide();
$boxOne.on('click', () => $boxTwo.show());
$boxTwo.on('click', () => {
console.log("Hello world!");
$boxTwo.hide();
});
.bx {
width: 200px;
height: 50px;
text-align: center;
font-weight: bold;
}
#bx-one { background-color: red; }
#bx-two { background-color: orange; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="bx-one" class="bx">Box one</div>
<div id="bx-two" class="bx">Box two</div>
yes the code I gave is simple ... But it does not perfectly illustrate my problem. In fact in my original code this is a dialog box that pops up when I click on a button, and this dialog box contains a "confirm" button. I want that when I click on the confirm button (Unlike the display of "hello world" in the console in this code) a confirmation message goes from the dialog box to the object that contains the first button that I clicked. So i told myself that the two click events must be connected. i could be wrong

When I click outside the `<html>`, why does it trigger the click event bound on `<html>`?

const html = document.querySelector('html')
const body = document.querySelector('body')
body.onclick = () => {
console.log('body clicked')
}
html.onclick = () => {
console.log('html clicked')
}
document.onclick = (e) => {
console.log('document clicked')
}
window.onclick = () => {
console.log('window clicked')
}
html {
width: 500px;
height: 500px;
border: 20px solid red;
margin-left: 100px;
margin-top: 100px;
}
body {
width: 300px;
height: 300px;
border: 20px solid green;
}
<div></div>
I have assigned a fixed width and height to the <html>(See the red box in the figure above.), When I click outside the red box, why does it trigger the click event bound on <html>?
When I click outside the red box, why does it trigger the click event
bound on ?
You've really clicked outside the red box, but it still relates to html tag. It means: the position where you're clicking on, it's still inside html tag.
You can use Dev tools to check that:
By hovering on html tag, you will see the real width/height of html tag is still full of the page.

If only div 1 is clicked, play sound

In my project, I have a big div, and there is another div in that div as a shape.
When you click the shape, you did right and you have 1 point. When you click only the background div, I want to play a sound.
When I do (simple example):
var $audioLifeLost = new Audio('Mis.mp3');
#divid.onclick = function (){
$audioLifeLost.play();
}
it also plays the sound when I hit the shape because I hit both div's at the same time.
Anyway how can I do it?
You need to stop the event from propagating up to the parent:
document
.querySelector('#inner')
.addEventListener('click', e => {
console.log('click inner');
e.stopPropagation(); // <-- stop event propagation
})
document
.querySelector('#outer')
.addEventListener('click', () => {
console.log('click outer');
})
#outer {
background: pink;
height: 300px;
width: 300px;
display: flex;
align-items: center;
justify-content: center;
}
#inner {
background: salmon;
width: 150px;
height: 150px;
}
<div id="outer">
<div id="inner"></div>
</div>
document.getElementById("divid").onclick = function (e) {
if (e.target == document.getElementById("divid"))
$audioLifeLost.play();
}

Jquery click on popup div to show another div

The requirement is user can Click on black box to show orange box, and click on orange box to show red box, but the orange box and red box should be hidden
when user click anywhere of the document except the orange box or the
red box itself.
But currently the issue is that we cannot click on orange box to show red box
Would much appreciate if you could help me out, thanks a lot
Demo link: http://plnkr.co/edit/OqlfbmFPKdXx0wDhnLxZ?p=preview
$(function() {
$('#mypop').click(function(e) {
event.stopPropagation();
});
$(document).on('click', '#myclick', function() {
$('#mypop').toggle();
$(document).one('click', function() {
$('#mypop').hide();
});
});
$(document).on('click', '#myclick1', function() {
$('#mypop2').show();
});
$(document).on('click', '#myclick2', function() {
$('#mypop2').show();
});
})()
#mypop {
background-color: orange;
position: absolute;
top: 130px;
left: 50px;
width: 150px;
padding: 15px;
}
.mydiv {
background-color: black;
padding: 30px;
width: 50px;
cursor: pointer;
color: white;
}
#mypop2 {
margin-top: 150px;
background-color: red;
width: 100px;
height: 50px;
padding: 18px;
display: none;
}
#myclick1,
#myclick2 {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myclick" class='mydiv black-box'>
click me!
</div>
<div id="mypop" style="display:none;" class='orange-box'>
<p>hello world</p>
<div id='myclick1'>BUTTON1</div>
<div id='myclick2'>BUTTON2</div>
</div>
<div id="mypop2" class='red-box'>
Hello World!!!
</div>
try this. I think this is what you are excepting but I'm not sure since you keep editing your question.
Demo Link: http://plnkr.co/edit/n7rdgqTwiFrXtpgoX4TQ?p=preview
$('#myclick1').click(function(){
$('#mypop2').show();
});
$('#myclick2').click(function(){
$('#mypop2').show();
});
You have couple of things mixed up.
The main stop-point was the very first event listener
$('#mypop').click(function(e) {
which is incompatible with the rest of listeners
$(document).on('click','#myclick1',function(e){
after I have changed it to
$(document).on('click','#mypop', function(e){
the other listeners have started working.
Second thing is that for embedded elements (parent-child) you need to stop event propagation, otherwise the parent event is triggered as well (which is not desired)
$(document).on('click','#myclick1',function(e){
e.stopPropagation();
:
});
I have also changed the CSS a bit and added class hide to use instead of styles. Toggling this class is what hides and shows an element.

Javascript will not wait for JQuery animation to finish before executing next command

I'm trying to create a simple 2-D game in Javascript. I'm going to use jQuery to do some animations.
There will be buttons that a player will use to call various functions (Move up/down/left/right, Attack, Defend, etc).
A movement() function will call a secondary function, animateCharacter(), to handle the movement of an image object on screen.
The problem I'm having is that the next command in the movement() function executes before the animateCharacter() function has finished.
I tried to add a callback function, but that didn't fix the situation. I've tried many other things -- setInterval, setTimeout, .delay, etc. Nothing seems to fix this situation. What am I not doing, or what am I doing wrong?
Here's a simplified example of the problem....
What I'm expecting to happen is the user hits [Move the Block], the image of a yellow face moves a bit to the right; then the mainContainer turns into "hello", and then turns into "goodbye."
But what happens instead is: The user hits [Move the Block], the mainContainer immediate says "goodbye", then the animation is never visible, but when the animation finishes, the mainContainer turns into "hello."
If I comment out the final command, the animation is seen and the mainContainer turns into "hello," as expected; but then I don't get to do the that final line of code.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
#mainContainer {
border: 1px solid gray;
width:100px;
height:100px;
position: relative;
}
#myObject {
border: 1px solid gray;
width: 30px;
height: 30px;
color:blue;
text-align:center;
background-color:yellow;
position:relative;
}
</style>
</head>
<body>
<div id="mainContainer">
<div id="myObject">:c)</div>
</div>
<script>
// MOVE THE BLOCK TO THE RIGHT
function animateCharacter(callbackSent) {
$("#myObject").animate({left: "+=50"},1500, function () { callbackSent();});
}
// DO THIS WHEN THE BUTTON IS PUSHED
function doTask() {
myCallback = function () { document.getElementById("mainContainer").innerHTML = "hello"; };
animateCharacter(myCallback);
// WORKS FINE IF THIS IS COMMENTED OUT,
// BUT I WANT MORE CODE TO EXECUTE
document.getElementById("mainContainer").innerHTML = "goodbye";
}
</script>
<button id="pushMe" onclick="doTask();">Move the Block</button>
</body>
</html>
Try This.
Moved document.getElementById("mainContainer").innerHTML = "goodbye"; to the setTimeout function, that will execute after Hello is printed in the div.
Your code was executing like:
Animate the box with 1500 miliseconds - Animation starts
Change main content to goodBye without waiting for animation completion - Right after animation start
Animation got Completed, so change content to Hello - Animation Completes, though the user never saw it.
// MOVE THE BLOCK TO THE RIGHT
function animateCharacter(callbackSent) {
$("#myObject").animate({left: "+=50"},1500, callbackSent);
}
// DO THIS WHEN THE BUTTON IS PUSHED
function doTask() {
myCallback = function () { document.getElementById("mainContainer").innerHTML = "hello";
setTimeout(function(){document.getElementById("mainContainer").innerHTML = "goodbye"; },1000);
};
animateCharacter(myCallback);
// WORKS FINE IF THIS IS COMMENTED OUT,
// BUT I WANT MORE CODE TO EXECUTE
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
#mainContainer {
border: 1px solid gray;
width:100px;
height:100px;
position: relative;
}
#myObject {
border: 1px solid gray;
width: 30px;
height: 30px;
color:blue;
text-align:center;
background-color:yellow;
position:relative;
}
</style>
</head>
<body>
<div id="mainContainer">
<div id="myObject">:c)</div>
</div>
<button id="pushMe" onclick="doTask();">Move the Block</button>
</body>
</html>
Your code does what it is told at the moment. You need to introduce a delay before showing goodbye.
// MOVE THE BLOCK TO THE RIGHT
function animateCharacter(callbackSent) {
$("#myObject").animate({
left: "+=50"
}, 1500, callbackSent);
}
// DO THIS WHEN THE BUTTON IS PUSHED
function doTask() {
animateCharacter(function () {
$("#mainContainer").html("hello");
setTimeout(function () {
$("#mainContainer").html("Goodbye");
}, 3000);
});
}
$('#pushMe').click(doTask);
JSFiddle: http://jsfiddle.net/TrueBlueAussie/7tucg2s5/1/
Notes:
I also used jQuery alternatives to shorten the code.
I moved your inline onclick handler to the jQuery equivalent as that is easier to maintain.
You can't put your "goodbye" message directly in #myContainer because this will destroy #myObject. Add another div to hold the message:
HTML:
<div id="mainContainer">
<div id="myObject">:c)</div>
<div id="myText"></div>
</div>
CSS:
#myText {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
JavaScript:
function doTask() {
myCallback = function () { document.getElementById("mainContainer").innerHTML = "hello"; };
animateCharacter(myCallback);
// WORKS FINE IF THIS IS COMMENTED OUT,
// BUT I WANT MORE CODE TO EXECUTE
document.getElementById("myText").innerHTML = "goodbye";
}
Fiddle here: http://jsfiddle.net/robbyn/0qkt0v5r/
Try
function animateCharacter() {
return $("#myObject").animate({
left: "+=50"
}, 1500, function() {
$(this)
.fadeOut(500)
.parent()
.html("<span>hello</span>")
.find("span")
.delay(1500, "fx")
.fadeOut(250, function() {
$(this).html("Goodbye").fadeIn(250)
})
})
}
$("#pushMe").on("click", function() {
animateCharacter()
});
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<style>
#mainContainer {
border: 1px solid gray;
width: 100px;
height: 100px;
position: relative;
}
#myObject {
border: 1px solid gray;
width: 30px;
height: 30px;
color: blue;
text-align: center;
background-color: yellow;
position: relative;
}
</style>
</head>
<body>
<div id="mainContainer">
<div id="myObject">:c)</div>
</div>
<button id="pushMe">Move the Block</button>
</body>
</html>

Categories

Resources