jquery hide div when click outside - javascript

I am trying to style div and ul to function like . However, I have a problem that:
1) I only want to toggle the ul that I click and hide the other ul. So I wonder if jquery support some function such as 'not click'?
2) I want to hide all the ul when the mouse is click outside. I did some research, and see other people use mouseup or click on body. But I am not quiet sure how it works.
$(document).ready(function() {
$('.hide').each(function() {
$(this).hide();
});
$('.select').click(function() {
var id = '#' + $(this).attr('id');
var sub = id + '_sub';
$(sub).slideToggle();
});
$('body').mouseup(function() {
if($(this).length == 0) {
$(this).hide();
}
});
});
div.select {
display: inline-block;
margin: 10px;
padding: 20px;
background: red;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="1" class="select">
<div class="main">
<span>1</span>
</div>
<div>
<ul id="1_sub" class="hide">
<li>1</li>
<li>2</li>
</ul>
</div>
</div>
<div id="2" class="select">
<div class="main">
<span>1</span>
</div>
<div>
<ul id="2_sub" class="hide">
<li>1</li>
<li>2</li>
</ul>
</div>
</div>
<div id="3" class="select">
<div class="main">
<span>1</span>
</div>
<div>
<ul id="3_sub" class="hide">
<li>1</li>
<li>2</li>
</ul>
</div>
</div>
</body>

here you go: DEMO
$(document).ready(function() {
$('.hide').hide(); //hide in the beginning
$('.select').click(function() {
$('.hide').slideUp(200); //hide all the divs
$(this).find('.hide').slideDown(200); //show the one that is clicked
});
$(document).click(function(e){
if(!$('.select').is(e.target) || !$('.select').has(e.target)){ // check if the click is inside a div or outside
$('.hide').slideUp(200); // if it is outside then hide all of them
}
});
});
you can define your notClick() function as below:
$.fn.notClicked= function(clickPosition){
if (!$(this).is(clickPosition.target) && $(this).has(clickPosition.target).length === 0){
return true;
}
else{
return false;
}
};
and then use it as:
$(document).click(function(e){
alert($('.select').notClick(e)); // will return true if it is not clicked, and false if clicked
});

You need to hide other ul whenever some one clicks on .select div.
Here is a working fiddle: http://jsfiddle.net/0mgbsa0b/1/
$(document).ready(function() {
$('.hide').each(function() {
$(this).hide();
});
$('.select').click(function() {
$('.hide').each(function() {
$(this).hide();
});
var id = '#' + $(this).attr('id');
var sub = id + '_sub';
$(sub).slideToggle();
});
$('body').mouseup(function() {
if($(this).length == 0) {
$(this).hide();
}
});
});

I'm interested in two concerns you raised, so i will be trying to share some ideas on them:
1)So I wonder if jquery support some function such as 'not click'?
personally, to quesiton1
i think there is no jQuery event method called .noclick()
PPL often use addClass & removeClass to log whether an element got clicked and after marking the element with class="active" , using jQuery selector to select ".active" or using jQuery ":not" selector to select elements that are not marked ".active" ( indirectly finding out those unclicked.)
3.You might also need to count in click propagation issues. meaning sometimes you click a children container and triggered click event towards all its parent inside.
fiddle link: `http://jsfiddle.net/hahatey/ctp5jngf/2/`
In the above case , if you clicked child box in red, will by default alert1, alert2 if
you didn't apply a e.stopPropagation() to the click event;
2) I want to hide all the ul when the mouse is click outside. I did some research, and see other people use mouseup or click on body. But I am not quiet sure how it works.
for question 2:
could be many many ways to do it, you can try blur() //lose focus event trigger.
like what you mentioned mouseout, mouseup, add click event listener to outer area all will work for it as long as u can use method in answer1. i see other ppl have posted many answers already as it can be done in many ways.

Related

how to add event listener to li thats inside a div

I have been trying to add an event listener to three li elements. The issue is that doing document.getElementbyid(about) doesn't work. But when I do get element document.getElementbyid(last), it works but on all three elements simultaneously.
I want to target them individually so that it opens up models respective to each li element.
Here is the HTML:
<section>
<h1 id="intro">Hi, My name is</h1>
<div id="last">
<ul>
<li id="about">About</li>
<li id="project">Projects</li>
<li id="resume">Resume</li>
</ul>
</div>
</section>
well like this :
let lis = document.querySelectorAll('section div ul li')
lis.forEach((li) => {
li.addEventListener('click', () => {
})
})
if you want you can handle each li individually like so :
let resume = document.querySelector('#resume')
resume.addEventListener('click', () => {
// do whatever you need
})
the click event here is an exemple, use the event you need, like perhaps mouseover
It is possible to add a click event to each element. You would use querySelectorAll to reference them all. You would then loop over it.
document.querySelectorAll("#last li").forEach(function (li) {
li.addEventListener("click", function () {
console.log("Clicked", li.id);
});
});
A better option is event delegation where you just bind one event.
Here is the basic idea using event delegation. Add one click event listener on a parent. You select the target which is what was clicked and find the link. You can use the link's hash to get the element you want to show.
// Bind one click event to the parent, we will use event delegation
document.getElementById("last").addEventListener("click", function(event) {
// get what was clicked and look for the anchor tag
const anchor = event.target.closest("a");
// did we find an anchor?
if (anchor) {
// hash will have the id of the element to show
showElement(anchor.hash);
}
});
function showElement(selector) {
// do we have an active modal? Yes? Close it
const modalActive = document.querySelector(".modal.active");
if (modalActive) {
modalActive.classList.remove('active');
}
// Enable the modal we just clicked on
const elem = document.querySelector(selector);
if (elem) {
elem.classList.add('active');
}
}
// Page load, if has hash then show that element
const hash = window.location.hash;
if (hash) {
showElement(hash);
}
.modal {
display: none;
}
.active {
display: block;
}
<section>
<h1 id="intro">Hi, My name is</h1>
<div id="last">
<ul>
<li>About</li>
<li>Projects</li>
<li>Resume</li>
</ul>
</div>
</section>
<div id="about" class="modal">ABOUT CONTENT</div>
<div id="project" class="modal">PROJECT CONTENT</div>
<div id="resume" class="modal">RESUME CONTENT</div>

Use jQuery to click anywhere and remove 'active' class

I'm having some trouble figuring out how to close a div by clicking anywhere on the screen.
I'm currently toggling an 'active' class in order to display a drop down div, then attempting to remove that class by clicking on the body:
$(document).ready(function () {
$('.navbar a').click(function () {
$(this).next('.navbar-dropdown').toggleClass('active');
});
$(body).click(function() {
if($('.navbar-dropdown').hasClass('active')){
$('.navbar-dropdown').removeClass('active');
}
});
});
<ul class="navbar">
<li>
Link
<div class="navbar-dropdown">
Dropdown Content
</div>
</li>
</ul>
However they are conflicting with each other, so as soon as the class is toggled on, the 'body' click toggles it off at the same time. Have spent some time looking on here and came across this method a few times:
$(document.body).click( function() {
closeMenu();
});
$(".dialog").click( function(e) {
e.stopPropagation();
});
However any attempts to configure this to work correctly seemed to fall on deaf ears!
The click event from the navbar is bubbling up to the body, so both events fire. stopPropagation() is one way to prevent that, but you need to do it in the navbar link's event handler, so it stops that particular event; not in a separate event handler as you had it.
Another change you might consider making is to only assign the body click handler when you need it, instead of firing all the time -- create that handler inside the navbar's click handler, and deactivate it again when it's used:
$(document).ready(function() {
$('.navbar a').click(function(e) {
var myDropdown = $(this).next('.navbar-dropdown');
$('.navbar-dropdown.active').not(myDropdown).removeClass('active'); // close any other open dropdowns
myDropdown.toggleClass('active'); // open this one
$('body').click(function() {
// no need for an if statement here, just use a selector that matches the active elements:
$('.navbar-dropdown.active').removeClass('active');
$('body').off('click'); // cancel the body's click handler when it's used
});
e.stopPropagation(); // prevent the navbar event from bubbling up to the body
});
});
.active {
color: red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="navbar">
<li>
Link
<div class="navbar-dropdown">
Dropdown Content
</div>
</li>
<li>
Link 2
<div class="navbar-dropdown">
Dropdown Content 2
</div>
</li>
<li>
Link 3
<div class="navbar-dropdown">
Dropdown Content 3
</div>
</li>
</ul>
(If there's a chance you might need more than one separate click event handler on the body, you can namespace the event so you can control which one you're turning off:
$('body').on("click.myNamespace", function() {
// do other stuff
$('body').off("click.myNamespace")
})
I did the exact thing as you and it works for me. Are you sure you don't have any other event listeners attached? Or maybe a z-index on the menu bringing it underneath other elements?
$(document).click(function(e) {
$(".dialog").text('closed')
});
$(".dialog").click(function(e) {
e.target.innerText = 'open';
e.stopPropagation();
});
.dialog {
width: 200px;
height: 200px;
background: antiquewhite;
text-align: center;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="dialog">open</div>
</body>
</html>

Toggle menu but also allows click inside without closing

Firstly apologies for the random title, I really can't think of another way to word it succinctly.
This is my issue.
I have a couple of nav icons, that when clicked toggle menu displays, just like you see everywhere: facebook, etc.
When you click outside of the div it hides the menu.
It works but I have two problems.
Clicking outside works to close the open div, but clicking on the icon that triggers the toggle doesn't close it, it just re-toggles it instantly.
I would like to be able to click inside of the menus without them closing, which they are currently doing onclick.
The html looks something like this, where the user-menu is the click-able icon that toggles the div contained within.
HTML
<nav>
<div class="user-menu">
<div id="user-dropdown">MENU CONTENTS HERE</div>
</div>
</nav>
jQuery
$('.user-menu').click(function () {
$('#user-dropdown').fadeToggle();
});
$(document).mouseup(function(e) {
var container = $("#user-dropdown");
if (!container.is(e.target) && container.has(e.target).length === 0) {
container.hide();
}
});
FIDDLE
https://jsfiddle.net/vo8a1r0p/
EDIT - ANSWER
Using a mixture of Bhuwan's answer and a stopPropagation() it's now working.
Working jQUERY
$(document).on("click", function(e) {
if ($(e.target).hasClass("user-menu")) {
$('#user-dropdown').fadeToggle();
} else {
if ($(e.target).hasClass("dropdown-menu")) {
$('#user-dropdown').show();
} else {
$('#user-dropdown').fadeOut();
}
}
});
$("#user-dropdown").click(function(e){
e.stopPropagation();
});
Working FIDDLE
https://jsfiddle.net/ne4yfbjp/
You can try this
$(document).on("click", function(e) {
if ($(e.target).hasClass("user-menu")) {
$('#user-dropdown').fadeToggle();
} else {
if ($(e.target).closest("#user-dropdown").hasClass("dropdown-menu")) {
$('#user-dropdown').show();
} else {
$('#user-dropdown').fadeOut();
}
}
});
.dropdown-menu {
display: none;
background: gray;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div>
<button class="user-menu">Menu</button>
<div id="user-dropdown" class="dropdown-menu">
<div class="username">
Some User
</div>
<ul>
<li>Link1</li>
<li>Link1</li>
</ul>
</div>
</div>
</nav>

Testing if a click is in a div and all its children

I am facing an issue about this.
<div id="1">
<div id="2">
</div>
<div id="3">
<div id="4">
</div>
</div>
</div>
<div id="others_div">
</div>
I want to add the class "hidden" to "1" when I click on something which is not "1" nor one of its children.
Now I am using this but I have a lack of imagination for solving this issue...
document.onclick = function(e)
{
if(e.target.id!="1")
{
$("#1").addClass("hidden");
}
}
Well, to avoid e.stopPropagation() (maybe you want that event to bubble up to some other ancestor) You can check if it is not clicked on #1 nor on it's children like this:
$('body').on('click', function(e) {
if (!((e.target.id== "1") || $(e.target).closest('#1').length)) {
$("#1").addClass("hidden");
}
});
You could use a jQuery check like the following one to check if the current element is your 1 element or traverse the DOM to see if the current target is contained within an element with an ID of 1 :
<script>
$(function(){
// Trigger this when something is clicked
$(document).click(function(e){
// Toggle the hidden class based on if the current element is 1
// or if it is contained in an element with ID of 1
$("#1").toggleClass('hidden',!((e.target.id== "1") || $(e.target).closest('#1').length))
});
});
</script>
Generally, you should avoid using ID attributes that only consists of numbers as they are not valid (ID attributes must begin with a letter). Ignoring this could result in some issues with regards to CSS or jQuery selection.
JQuery
$('body').on( "click", function(e) {
if(e.target.id !== "1")
{
$("#1").addClass("hidden");
}
});
I think you want this
// taken from http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element
$('html').click(function() {
//Hide the menus if visible
alert('hide');
});
$('#one').click(function(event){
event.stopPropagation();
});
div#one {
background: yellow;
}
div#others_div {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="one">
div one
<div id="2">
div two
</div>
<div id="3">
div three
<div id="4">
div four
</div>
</div>
</div>
<div id="others_div">
other div
</div>

How do I make a .hover div stay open while the mouseover is still on the parent?

First things first, a fiddle: http://jsfiddle.net/d7wfv8w8/
I have a navbar with a logo, search form and a Categories link. When somebody moves over it with the mouse, it should open the wrapper-categories div, which is display: none; by default.
I got it working, except the div is closing when you then move the mouse over the div that opened. I thought I could get it to stay open if I used .navbar .toggle to tell it that the parent is .navbar and it should stay open as long as the mouse is anywhere over that parent div.
How can I achieve this?
Here is my HTML:
<div class="navbar">
<div class="wrapper-header">
<ul>
<li class="">Logo Here</li>
<li class="">Search Here</li>
<li class="">Categories</li>
</ul>
</div>
<div class="wrapper-categories">
Categories Here
</div>
</div>
And the jQuery:
$(".navbar .toggle").hover(function (event){
event.preventDefault();
$(".wrapper-categories").slideToggle("fast");
});
You can achieve this by binding the hover function to the element wrapping both wrapper-header and wrapper-catagories. This will cause the hoverOut to only be called when it leaves the wrapper for both elements. Keeping both of your required divs open.
Fiddle: http://jsfiddle.net/d7wfv8w8/5/
Late to the party but change your class' to ID's and give this a go. Works for me.
$(document).ready(function(){
$( "#toggle" ).hover(
function() {
$( "#wrapper-categories" ).slideDown({
left: "+=50",
height: "toggle"
}, 500, function() {
// Animation complete.
});
}
);
var inArr = {toggle:false, wrapper-categories:false};
$('#toggle, #wrapper-categories').mouseover(function(){
inArr [$(this).attr('id')] = true;
});
$('#toggle, #wrapper-categories').mouseout(function(){
inArr [$(this).attr('id')] = false;
setTimeout(function(){
if(!inArr.toggle && !inArr.wrapper-categories) {
$('#navArea').slideUp(500);
}
},100);
});
});

Categories