Reputation: 723
I can hide child element with add every child element this code:
window.addEventListener('mouseup', function(event){
let children = parent[0].children[0]
if (event.target != children && event.target.parentNode != children){
children.style.display = 'none';
}
});
But how can hide child ul element clicking outside child ul element(with for loop or something else) without add this code every child element?
In this code I show child ul element when clicking parent li element
var parent = document.querySelectorAll('body > ul > li');
parent[0].addEventListener('click', function () {
parent[0].children[0].style.display = 'block';
});
parent[1].addEventListener('click', function () {
parent[1].children[0].style.display = 'block';
});
parent[2].addEventListener('click', function () {
parent[2].children[0].style.display = 'block';
});
window.addEventListener('mouseup', function(event){
let children = parent[0].children[0]
if (event.target != children && event.target.parentNode != children){
children.style.display = 'none';
}
});
ul > li > ul {
display: none;
}
ul, li {
width: max-content;
}
<ul>
<li>parent1
<ul>
<li>child1</li>
</ul>
</li>
<li>parent2
<ul>
<li>child2</li>
</ul>
</li>
<li>parent3
<ul>
<li>child3</li>
</ul>
</li>
</ul>
Thanks
Upvotes: 0
Views: 354
Reputation: 269
If I understand your problem: User clicks on any of the child elements, there should not be any change in the child state (hide). You can use the below code (I am assuming that you are using ES5 only). If you want to hide the child elements on parent click, then remove the isParentClick()
method.
var parent = document.querySelectorAll('body > ul > li');
var len = parent.length;
for(var i=0;i<len;i++){
parent[i].addEventListener('click', function (event) {
if(event.target !== event.currentTarget.children[0].children[0]){
if(event.currentTarget.children[0].style.display === 'block'){
event.currentTarget.children[0].style.display = 'none';
} else {
event.currentTarget.children[0].style.display = 'block';
}
}
});
}
window.addEventListener('mouseup', function(event){
if(isParentClick()){
return false;
}
if(isChildClick(event)){
return false;
}
for(var i=0;i<len;i++){
parent[i].children[0].style.display = 'none';
}
});
function isParentClick(){
for(var i=0;i<len;i++){
if(parent[i] === event.target){
return true;
}
}
return false;
}
function isChildClick(event){
for(var i=0;i<len;i++){
if(parent[i].children[0].children[0] === event.target){
return true;
}
}
return false;
}
ul > li > ul {
display: none;
}
ul, li {
width: max-content;
}
<ul>
<li>parent1
<ul>
<li>child1</li>
</ul>
</li>
<li>parent2
<ul>
<li>child2</li>
</ul>
</li>
<li>parent3
<ul>
<li>child3</li>
</ul>
</li>
</ul>
Upvotes: 1
Reputation: 50291
You can use document.querySelectorAll
instead of targeting individual elements
Since to display the child the click will be on li
so again do a querySelector
and select ul
and add the style.
Note use of stopPropagation
.There is another event attached to body
so that any click on body
will hide the child. The usage of stopPropagation is to prevent the event from bubling
phase the click on li and click on body both will happen simultaneously.
The body is bordered in red
var parent = document.querySelectorAll('body > ul > li');
parent.forEach(function(item) {
item.addEventListener('click', function(e) {
e.stopPropagation()
item.querySelector('ul').style.display = 'block';
})
document.body.addEventListener('click', function(e) {
document.querySelectorAll('.parent').forEach(function(item) {
item.querySelector('ul').style.display = 'none'
})
})
})
ul>li>ul {
display: none;
}
ul,
li {
width: max-content;
}
body {
border: 1px solid red;
}
<ul>
<li class='parent'>parent1
<ul>
<li>child1</li>
</ul>
</li>
<li class='parent'>parent2
<ul>
<li>child2</li>
</ul>
</li>
<li class='parent'>parent3
<ul>
<li>child3</li>
</ul>
</li>
</ul>
Upvotes: 1