Jquery closing on parent click - javascript

I want a window to close only when pop_up is clicked (as opposed to clicking div contents). E.g. clicking the background layer hides the div. In the code below I don't want it to close #pop_up when clicking the div contents bot only on "pop_up".
How can I do this?
$("#pop_up").click(function() {
$("#pop_up").hide();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pop_up">
<div id="pop_up_content">
<h1> world </h1>
</div>
</div>

What you are experiencing is the bubbling and capturing behaviour of events.
Check this answer What is event bubbling and capturing? .
The simples approach would be to attach a onClick to the child and stop the bubbling.
$("#pop_up_content").click(function(ev) {
ev.preventDefault()
ev.stopImmediatePropagation() // best to use to stop other event listeners from being called
});

You can use the event argument of the click, and see if the click is inside another element (or it is the element itself)
JSFiddle: https://jsfiddle.net/32mz2x3x/1/
$("#pop_up").click(function(event) {
if ($(event.target).parents().andSelf().is('#pop_up_content')) {
return
}
$("#pop_up").hide();
});
I have used parents to check if where you click is inside pop_up_content element, and I used andSelf because maybe you click on #pop_up_content (and not inside it)
More info:
jQuery andSelf function
jQuery is function
jQuery parents function
jQuery event object

use the form that allows a filter selector, combined with :not():
$("#pop_up").on('click', ':not(#pop_up_content)', function (e) {
$("#pop_up").hide();
});

JSBin: http://jsbin.com/hoyizos/edit?html,css,js,output
$("#pop_up").click(function(e) {
if ($(event.target).is($("#pop_up"))){
$("#pop_up").hide();
}
});
h1{
margin:50px 50px;
background-color:red;
display:inline;
}
#pop_up_content{
background-color:yellow;
}
#pop_up{
margin:10px;
background-color:green;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://code.jquery.com/jquery-3.0.0.js"></script>
</head>
<body>
<div id="pop_up">
<div id="pop_up_content">pop_up_content
<h1> world </h1>
</div>
I am the pop_up!
</div>
</body>
</html>
Don't cancel event bubbling!: The Dangers of Stopping Event Propagation, use it only if there is no other way.
Don't use andSelf() if you plan to use jQuery 3.x, because it is deprecated since v1.8 and will be removed in jQuery v3.
Note: This function has been deprecated and is now an alias for
.addBack(), which should be used with jQuery 1.8 and later.
If you use jQuery 1.8 < use addBack instead.

Related

JavaScript, clicking button activates parent event listener

I have two buttons on my page that I use to try new things. Both of them use the "onclick" linked to a different JS function.
For some reason the second one activates both? And I can't figure out what I've done wrong.
The HTML looks like this:
<!DOCTYPE html>
<html>
<head>
<link HREF="styleTest.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Serif:ital,wght#0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght#0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<script type="text/javascript" src="script.js"></script>
<title>TEST</title>
</head>
<body>
<div class="page">
<div class="nav-container" onclick="hamburger(this)">
<div class="ham-container">
<div class="hamburger-1"></div>
<div class="hamburger-2"></div>
<div class="hamburger-3"></div>
</div>
<div class="nav-bar">
<a>Home</a>
<a>Services</a>
<a>About</a>
<a>Projects</a>
</div>
<div class="button-test">
<button onclick="clickTest()">CLICK ME</button>
<h1>Test text</h1>
</div>
</div>
</body>
And the two JS functions:
function hamburger(x) {
x.classList.toggle("change");
}
var i =0
function clickTest() {
i++;
console.log(i)
}
What am I doing wrong?
When you trigger an event on an element, it will sequentially be triggered for its father, for its grandfather... all the way to the last parent element. Often we don't see this behaviour happening because often we have one event listener in an elements' family.
But if the triggered element is inside a parent that has an event listener for the same event, like in your case, both of them will be triggered. However you can prevent this behaviour with the help of stopPropagation method, this way:
function clickTest(e) {
e.stopPropagation();
i++;
console.log(i)
}
This happens because of a concept known as Bubbling in DOM .
When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.
Try playing around with this snippet below .
<style>
body * {
margin: 10px;
border: 1px solid blue;
}
</style>
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
A click on the inner <p> first runs onclick:
On that <p>.
Then on the outer <div>.
Then on the outer <form>.
And so on upwards till the document object.
Please refer this page for more clarity : Link
The way event listeners works is that when you have a nested object
(For example button inside a div)
And both of them has event listeners , when you click on the inner element (button) the event listener of the button will first be fired before the parent event listener
To solve this, you have to stop the propagation using this code
<button onclick="clickTest(event)">CLICK ME</button>
And the script
function clickTest(e) {
e.stopPropagation();
i++;
console.log(i)
}

What does this block of JavaScript code do?

I am very new to JavaScript, jQuery and HTML etc. And I am supposed to implement this block of code (below) in a project and I am not quite sure what it is meant to do:
$(document).ready(function(){
$("body").click(function(){
$(this).hide();
});
});
I'm assuming it simply hides any element that is clicked.
You are correct, it hides everything inside of the HTML element. It is also important to note that it is written using jQuery, which is a JavaScript library that has helper functions to make JavaScript more accessible to use.
Here is one line at a time:
Wait for the page to finishing loading in the browser (aka the DOM, or document object model):
$(document).ready(function(){
});
When the user fires the click event on the body element, run the following function:
$("body").click(function(){
});
Hide the body:
$(this).hide();
this (in this context) refers to the body element targeted in the previous line, this is the same as writing: `$('body').hide();
this refers to something different based on the context in which it is used. In this example it is used in an event, so it refers to the element that received that event (body). See W3Schools.
.hide() is a built in jQuery function that sets the element to display: none;
$(document).ready is called when the page is ready for javascript to be executed. $("body") selects the body, the body of the document is where all of the visible HTML elements are shown. The click event is triggered when well, the element is clicked. $(this) selects the current element being operated on, which is the body. the hide function hides the selected element, which in this case is the body. So this code hides the body of the HTML page resulting in all visual elements being hidden.
It's simple, it puts an "on click" event on the body element.
So that means, when you click the body element. It will hide everything in between the opening <body> and the closing </body> tags
<body>
<!--everything in here will be hidden once body element is clicked-->
</body>
That code will make it so that clicking on any element on the page will cause the body element to hide.
That is - unless the element has it's own onclick functionality assigned that stops the event from bubbling up to the body element's onclick by using the event.stopPropagation() function.
Note: You could also have a call to event.stopPropagation() within the event handler rather than just having it as the event handler.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("body").click(function() {
$(this).hide();
});
});
</script>
<html>
<head>
<title>Testing javascript function</title>
</head>
<body>
<p>Here is one paragraph</p>
<p>Here is a second paragraph</p>
<p>Clicking on any element will hide the entire body element.</p>
<input type="button" value="random button" onclick="event.stopPropagation()" />
</body>
</html>
It is pretty straight forward.
Sample HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
...
</body>
</html>
Js:
$(document).ready(function(){ //executes when document model is ready
$("body").click(function(){ //once u click anywhere on the page this function will be executed
$(this).hide(); //hides everything between <body></body>
});
});

fadeToggle with text() bug?

I'm trying to make a fadeToggle effect on jQuery,
the toggle effect works fine only in the second click on the <h1> tag.
in the first click it showing up and hide right after.
noticed that if I remove the text("how are you") method and put the inside the paragraph tag, it works perfectrly.
wondering why it doesn't work the first way.
This is my HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$('h1').click(function(){
$('p').text("how are you").fadeToggle(500);
});
});
</script>
</head>
<body>
<h1>Hello jquery</h1>
<p></p>
</body>
</html>
fadeToggle works the same way as e.g. toggle (applies opposed attribute). And since the default state for the p element at the begininng is display: inline (is visible), then the next default action will be hiding it. That's why you have to define it initially as hidden.
$(document).ready(function() {
$('h1').click(function() {
$('.x').text("how are you").fadeToggle(500);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Hello jquery</h1>
<p class='x' hidden></p>
It works correctly actually - the paragraph element is shown and by clicking on the heading, the function inserts text in it and then toggles fade. As the element is shown, by default (since there are no rules attached to it that would otherwise hide it), the fadeToggle will transition from shown to hidden state.
As stated in the comment above, to make fadeToggle begin by fading an element in, you should first hide the element (either via CSS or via JS, depending on your needs).

Class toggle in jQuery

Below is my code that is suppose to be a script that changes the color of the square after you click on in using toggleclass() method in jquery. I think my code is right but I can not get the square to change color. what am I doing wrong? thanks
Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<script src="js/jquery-1.11.1.min.js"></script>
<script type="text/javascript" language="javascript">
<script>
$( "p" ).click(function() {
$( this ).toggleClass( "p.over" );
});
</script>
<style>
p { background:#DAA520; font-weight:bold; cursor:pointer;
padding:5px;width:20%;}
p.over { background: #ADFF2F; }
span { color:red; }
</style>
</head>
<body>
<p>Click or double click here.</p>
<span></span>
</body>
</html>
Fix the toggleClass call, you only need the class name, not the selector: toggleClass('over') instead of toggleClass('p.over').
Then, you have two opening script tags:
<script type="text/javascript" language="javascript">
<script>
Remove the first one.
Next, you're binding an event listener to an element that's not in the DOM yet at the time the script executes.
Simple fix: move the script to the bottom of the page.
Another way: either execute the script when the DOM is ready (by wrapping it inside a document ready callback: $(document).ready()) or use dynamic binding using jQuery's on function.
Here is a working version: http://jsfiddle.net/7g95yvyo/
And the last, but not the least, learn to use browser's console - it will help you tremendeously while learning and debugging JavaScript.
css class is a .whatever rule, You don't have any classes in your CSS definitions, just elements.
.foo { color: puce } /* this is a class */
p { color: chartreuse } /* this is an element */
p.foo { color: aubergine } /* this is an element AND a class */
toggleClass('foo');
You're toggling on element.class, but toggleClass expects ONLY a class, not the element.

iPhone/Android browser occasionally follows link href instead of jQuery onclick event

I have a mobile web gallery page where I have a CSS floated "next" link. The CSS float property causes the link to have a display: block behavior on it. A jQuery touchstart event is bound to the link. When the user clicks on the link, the Javascript code bound to that touchstart event advances the gallery by one slide via Ajax. In other words, there is no page refresh.
However, I noticed that occasionally when I touch an area of the link's block space that is not the link text itself, the browser follows the href and causes a page refresh (because the URL has changed) instead of executing the Javascript code bound to the touchstart event.
Has anybody seen this before? Is there a way to fix this?
I simplified it down to this code below, and it still happens, although much less frequently.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<title>Test</title>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.js'></script>
<style type='text/css'>
.cont { width: 320px; }
.next { border-left: 1px solid #000; float: right; text-align: right; width: 65px; }
.msg { clear: both; width: 200px; }
</style>
<script type='text/javascript'>//<![CDATA[
$(function(){
$('.next').bind('click touchstart', function(event) {
event.preventDefault();
if (event.type == 'touchstart') {
$(this).unbind('click');
}
$('.msg').append('<p>Click!</p>');
});
});//]]>
</script>
</head>
<body>
<div class="cont">Next</div>
<div class="msg"></div>
</body>
</html>
I tested this on my iPhone and it seems to work. For some reason after registering a touchstart event you are unbinding the click events. Is there any reason for that?
When you click on the text of the link all it seems to register is indeed touch start, so unbinding click does not break things. I do believe, however, that when you touch outside the text link, but still within the block space it registers both a touchstart and click, so at this point you have already unbound click and it works as a regular link.
You should notice, that on your first click outside the bounds it never goes to yahoo.com. It's only the subsequent once that do that.
So in essence what you need to do is remove that unbind, as so:
<script type='text/javascript'>//<![CDATA[
$(function(){
$('.next').bind('click touchstart', function(event) {
event.preventDefault();
$('.msg').append('<p>Click!</p>');
});
});//]]>
</script>
Is there any reason why you would want to unbind click?

Categories