Fire only when clicking on parent element JavaScript - javascript

I have 2 collapsible nested inside each other
When clicking on Test 7, it closes both the BRAND and test 7 accordions
I have this JavaScript code where "mobile-nav_accordion-contentbox" is the className of the parent element (BRAND)
const mobile_navbar_accordion = document.getElementsByClassName("mobile-nav_accordion-contentbox");
for (let i = 0; i < mobile_navbar_accordion.length; i++) {
let checkbox = mobile_navbar_accordion[i];
checkbox.addEventListener("click", (e) => {
e.currentTarget.classList.toggle("active");
})
}
Solutions I tried:
Adding e.stopPropagation(); inside the click event
Replacing e.currentTarget with e.target but the click event is never working on the parent element, I tested this with the following code
if (e.target == e.currentTarget) console.log("clicked on parent");
else console.log("clicked on children")
I also tried
if(e.target == this) console.log("clicked on parent")
else console.log("clicked on children")
In both cases it returned "clicked on children"
I replaced e.currentTarget with this
this.classList.toggle('..')
And in the console I received this error
pointer-events: none;
In css for the children box, also for children title + content separately but it caused 2 issues, first stopping (Test 5, Test 6) from firing the link event. However it still didn't stop closing the parent when clicking on children box or children elements
const mobile_navbar_accordion = document.getElementsByClassName("mobile-nav_accordion-contentbox");
const mobile_navbar_accordion_grandchildren = document.getElementsByClassName("mobile-nav_accordion-contentbox__grandchildren");
for (let i = 0; i < mobile_navbar_accordion.length; i++) {
let checkbox = mobile_navbar_accordion[i];
checkbox.addEventListener("click", (e) =>
e.currentTarget.classList.toggle("active")
)
}
for (let i = 0; i < mobile_navbar_accordion_grandchildren.length; i++) {
let checkbox = mobile_navbar_accordion_grandchildren[i];
checkbox.addEventListener("click", (e) =>
e.currentTarget.classList.toggle("active")
)
}
ul{
list-style: none;
}
a{
color: black;
text-decoration: none;
padding: 10px 0;
}
.mobile-nav_accordion,
.mobile-nav_accordion__grandchildren{
width: 600px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox,
.mobile-nav_box {
position: relative;
margin-bottom: 1.5rem;
width: 100%;
}
.mobile-nav_accordion-contentbox__grandchildren {
position: relative;
width: 100%;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren{
position: relative;
width: 100%;
padding: 20px 0;
}
/* For + sign after each collapsible title */
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "+";
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "-";
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-content__grandchildren
{
position: relative;
height: 0;
overflow: hidden;
padding: 0 0.5rem;
transition-property: all;
transition-duration: 0.1s !important;
transition-timing-function: linear;
}
.mobile-nav_accordion-contentbox-content__grandchildren{
padding-left: 1rem;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-content__grandchildren{
height: max-content;
padding: 0.5rem;
}
.mobile-nav__links,
.mobile-nav_accordion-contentbox-label__grandchildren h5{
font-size: 13px;
margin-top: 1rem;
color: #3c3c3c;
}
<div class="mobile-nav_accordion">
<div class="mobile-nav_accordion-contentbox">
<label class="mobile-nav_accordion-contentbox-label">
BRAND
</label>
<div class="mobile-nav_accordion-contentbox-content">
<ul class="navigation-item-children--top-level">
<li>
<a class="mobile-nav__links" href="#">
<span>
Hello World 1
</span>
</a>
<!-- HERE GOES THE GRANDCHILDS -->
<div class="mobile-nav_accordion__grandchildren">
<div class="mobile-nav_accordion-contentbox__grandchildren">
<label class="mobile-nav_accordion-contentbox-label__grandchildren">
Test 1
</label>
<div class="mobile-nav_accordion-contentbox-content__grandchildren">
<ul>
<li>
<a class="mobile-nav__links" href="#">
Hello world
</a>
</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>

I think you can basically change your script to the provided version below.
const mobile_navbar_accordion = document.getElementsByClassName("mobile-nav_accordion-contentbox-label");
const mobile_navbar_accordion_grandchildren = document.getElementsByClassName("mobile-nav_accordion-contentbox-label__grandchildren");
for (let i = 0; i < mobile_navbar_accordion.length; i++) {
let checkbox = mobile_navbar_accordion[i];
checkbox.addEventListener("click", function(e){
// getting the parent element to add active
e.currentTarget.closest('.mobile-nav_accordion-contentbox').classList.toggle("active")
})
}
for (let i = 0; i < mobile_navbar_accordion_grandchildren.length; i++) {
let checkbox = mobile_navbar_accordion_grandchildren[i];
checkbox.addEventListener("click", function(e){
e.stopPropagation();
// getting the parent element to add active
e.currentTarget.closest('.mobile-nav_accordion-contentbox__grandchildren').classList.toggle("active")
} )
}
ul{
list-style: none;
}
a{
color: black;
text-decoration: none;
padding: 10px 0;
}
.mobile-nav_accordion,
.mobile-nav_accordion__grandchildren{
width: 600px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox,
.mobile-nav_box {
position: relative;
margin-bottom: 1.5rem;
width: 100%;
}
.mobile-nav_accordion-contentbox__grandchildren {
position: relative;
width: 100%;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren{
position: relative;
width: 100%;
padding: 20px 0;
}
/* For + sign after each collapsible title */
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "+";
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "-";
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-content__grandchildren
{
position: relative;
height: 0;
overflow: hidden;
padding: 0 0.5rem;
transition-property: all;
transition-duration: 0.1s !important;
transition-timing-function: linear;
}
.mobile-nav_accordion-contentbox-content__grandchildren{
padding-left: 1rem;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-content__grandchildren{
height: max-content;
padding: 0.5rem;
}
.mobile-nav__links,
.mobile-nav_accordion-contentbox-label__grandchildren h5{
font-size: 13px;
margin-top: 1rem;
color: #3c3c3c;
}
<div class="mobile-nav_accordion">
<div class="mobile-nav_accordion-contentbox">
<label class="mobile-nav_accordion-contentbox-label">
BRAND
</label>
<div class="mobile-nav_accordion-contentbox-content">
<ul class="navigation-item-children--top-level">
<li>
<a class="mobile-nav__links" href="#">
<span>
Hello World 1
</span>
</a>
<!-- HERE GOES THE GRANDCHILDS -->
<div class="mobile-nav_accordion__grandchildren">
<div class="mobile-nav_accordion-contentbox__grandchildren">
<label class="mobile-nav_accordion-contentbox-label__grandchildren">
Test 1
</label>
<div class="mobile-nav_accordion-contentbox-content__grandchildren">
<ul>
<li>
<a class="mobile-nav__links" href="#">
Hello world
</a>
</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>

Related

Link to several sliders on the same page

I always used the script from this answer from #Sushanth -- to slide images on single pages. It's perfect.
The problem, it only works on one slider per page, now I'm in a project where I have to place different small sliders associated with buttons and obviously, it doesn't work, or rather, only the first one works. It has taken me a long time to understand the script, as I have read in other answers, I guess it's something about assigning a different ID to each slider, but I cannot find the solution.
In the example snippet, the round button links to the first slider, the one that works. The square button links to the second slider (with three slides) but it doesn't work. Since sliders are links, each slider has its own set of next, prev, and close buttons.
var $first = $('li:first', 'ul'),
$last = $('li:last', 'ul');
// Have the first and last li's set to a variable
$("#next").click(function() {
var $next,
$selected = $(".selected");
// get the selected item
// If next li is empty , get the first
$next = $selected.next('li').length ? $selected.next('li') : $first;
$selected.removeClass("selected");
$next.addClass('selected');
// hides target
$('li').removeClass("linked");
});
$("#prev").click(function() {
var $prev,
$selected = $(".selected");
// get the selected item
// If prev li is empty , get the last
$prev = $selected.prev('li').length ? $selected.prev('li') : $last;
$selected.removeClass("selected");
$prev.addClass('selected');
// hides target
$('li').removeClass("linked");
});
* {
text-decoration: none;
}
.pre,
.post,
.fstbutton,
.scndbutton,
.BACK {
cursor: pointer;
z-index: 1500;
color: #C2C6D2;
font-size: 3rem;
margin-top: 3rem;
}
.fstbutton:before {
font-family: 'Font Awesome 5 free';
content: "\f111";
font-weight: 900;
}
.scndbutton:before {
font-family: 'Font Awesome 5 free';
content: "\f0c8";
font-weight: 900;
}
.pre:before {
font-family: 'Font Awesome 5 free';
content: "\f060";
font-weight: 900;
}
.post:before {
font-family: 'Font Awesome 5 free';
content: "\f061";
font-weight: 900;
}
.BACK:before {
font-family: 'Font Awesome 5 free';
content: "\f00d";
font-weight: 900;
}
/* pop-up */
.popup {
position: fixed;
top: 0;
padding-top: 2rem;
width: 100%;
height: 100%;
display: none;
text-align: center;
background: #ecf0fa;
z-index: 20;
opacity: 1;
overflow: hidden;
}
.popup:target {
display: block;
-webkit-animation-name: fadein 0, 2s;
animation-name: fadein;
animation-duration: 0.2s;
height: 100%;
}
/*SLIDER*/
.SLIDER {
position: absolute;
top: -1.4rem;
right: 7rem;
display: flex;
gap: 1.5rem;
}
li {
display: none;
width: fit-content;
height: fit-content;
padding: 1rem 2rem;
}
.selected,
.linked:last-child {
display: block;
}
/*FIN SLIDER*/
.yl {
background: yellow;
}
.br {
background: brown;
}
.bl {
background: blue;
}
.pi {
background: pink;
}
.re {
background: red;
}
.or {
background: orange;
}
.cy {
background: cyan;
}
.gr {
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css">
<a class="fstbutton" href="#firstslider"></a>
<a class="scndbutton" href="#scndslider"></a>
<div id="firstslider" class="popup">
<ul>
<li class="linked yl">
<h3>Yellow</h3>
</li>
<li class="linked bl">
<h3>Blue</h3></li>
<li class="linked br">
<h3>Brown</h3></li>
<li class="linked cy">
<h3>Cyan</h3></li>
<li class="linked gr">
<h3>Green</h3></li>
</ul>
<div class="SLIDER">
<div id="prev" class="pre"></div>
<div id="next" class="post"></div>
<div class="BACK" onClick="history.go(-1);return true;"></div>
</div>
</div>
<div id="scndslider" class="popup">
<ul>
<li class="linked pi">
<h3>Pink</h3>
</li>
<li class="linked re">
<h3>Red</h3></li>
<li class="linked or">
<h3>Orange</h3></li>
</ul>
<div class="SLIDER">
<div id="prev2" class="pre"></div>
<div id="next2" class="post"></div>
<div class="BACK" onClick="history.go(-1);return true;"></div>
</div>
</div>
The easiest way is to bind click events using different IDs for prev and next element.
Here I used #prev2 and #next2, and duplicated your functions, limiting each set of buttons to #firstslider and #scndslider
var $first = $('#firstslider li:first'),
$last = $('#firstslider li:last');
var $first2 = $('#scndslider li:first'),
$last2 = $('#scndslider li:last');
// Have the first and last li's set to a variable
$("#next").click(function() {
var $next,
$selected = $("#firstslider .selected");
// get the selected item
// If next li is empty , get the first
$next = $selected.next('li').length ? $selected.next('li') : $first;
$selected.removeClass("selected");
$next.addClass('selected');
// hides target
$('li').removeClass("linked");
});
$("#prev").click(function() {
var $prev,
$selected = $("#firstslider .selected");
// get the selected item
// If prev li is empty , get the last
$prev = $selected.prev('li').length ? $selected.prev('li') : $last;
$selected.removeClass("selected");
$prev.addClass('selected');
// hides target
$('li').removeClass("linked");
});
// Have the first and last li's set to a variable
$("#next2").click(function() {
var $next,
$selected = $("#scndslider .selected");
// get the selected item
// If next li is empty , get the first
$next = $selected.next('li').length ? $selected.next('li') : $first2;
$selected.removeClass("selected");
$next.addClass('selected');
// hides target
$('li').removeClass("linked");
});
$("#prev2").click(function() {
var $prev,
$selected = $("#scndslider .selected");
// get the selected item
// If prev li is empty , get the last
$prev = $selected.prev('li').length ? $selected.prev('li') : $last2;
$selected.removeClass("selected");
$prev.addClass('selected');
// hides target
$('li').removeClass("linked");
});
* {
text-decoration: none;
}
.pre,
.post,
.fstbutton,
.scndbutton,
.BACK {
cursor: pointer;
z-index: 1500;
color: #C2C6D2;
font-size: 3rem;
margin-top: 3rem;
}
.fstbutton:before {
font-family: 'Font Awesome 5 free';
content: "\f111";
font-weight: 900;
}
.scndbutton:before {
font-family: 'Font Awesome 5 free';
content: "\f0c8";
font-weight: 900;
}
.pre:before {
font-family: 'Font Awesome 5 free';
content: "\f060";
font-weight: 900;
}
.post:before {
font-family: 'Font Awesome 5 free';
content: "\f061";
font-weight: 900;
}
.BACK:before {
font-family: 'Font Awesome 5 free';
content: "\f00d";
font-weight: 900;
}
/* pop-up */
.popup {
position: fixed;
top: 0;
padding-top: 2rem;
width: 100%;
height: 100%;
display: none;
text-align: center;
background: #ecf0fa;
z-index: 20;
opacity: 1;
overflow: hidden;
}
.popup:target {
display: block;
-webkit-animation-name: fadein 0, 2s;
animation-name: fadein;
animation-duration: 0.2s;
height: 100%;
}
/*SLIDER*/
.SLIDER {
position: absolute;
top: -1.4rem;
right: 7rem;
display: flex;
gap: 1.5rem;
}
li {
display: none;
width: fit-content;
height: fit-content;
padding: 1rem 2rem;
}
.selected,
.linked:last-child {
display: block;
}
/*FIN SLIDER*/
.yl {
background: yellow;
}
.br {
background: brown;
}
.bl {
background: blue;
}
.pi {
background: pink;
}
.re {
background: red;
}
.or {
background: orange;
}
.cy {
background: cyan;
}
.gr {
background: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css">
<a class="fstbutton" href="#firstslider"></a>
<a class="scndbutton" href="#scndslider"></a>
<div id="firstslider" class="popup">
<ul>
<li class="linked yl">
<h3>Yellow</h3>
</li>
<li class="linked bl">
<h3>Blue</li>
<li class="linked br">
<h3>Brown</li>
<li class="linked cy">
<h3>Cyan</li>
<li class="linked gr">
<h3>Green</li>
</ul>
<div class="SLIDER">
<div id="prev" class="pre"></div>
<div id="next" class="post"></div>
<div class="BACK" onClick="history.go(-1);return true;"></div>
</div>
</div>
<div id="scndslider" class="popup">
<ul>
<li class="linked pi">
<h3>Pink</h3>
</li>
<li class="linked re">
<h3>Red</li>
<li class="linked or">
<h3>Orange</li>
</ul>
<div class="SLIDER">
<div id="prev2" class="pre"></div>
<div id="next2" class="post"></div>
<div class="BACK" onClick="history.go(-1);return true;"></div>
</div>
</div>

how to auto slide carousel to the first item after it reach the last item?

I have an automatic sliding carousel which is working fine except that when it reach the last image then it just freeze on the last image instead of auto slide to the first image. I just can't remake my javascript code alone. Strange but autosliding to the first image was working a few months ago. I had nothing change to the code but seems after last updates of chrome its just not working correctly neither on pc neither on mobile devices. Here is my javascript code:
const carousels = document.querySelectorAll('.img-carousel');
const prevBtn = document.querySelectorAll('.prev');
const nextBtn = document.querySelectorAll('.next');
let carsouselImages = document.querySelectorAll('.img-carousel div');
//Next Carousel
carousels.forEach((carousel, index)=>{
const nextCarousel = () => {
if(carsouselImages[carsouselImages.length - 1]) {
carousel.scrollTo(0, 0);
}
carousel.scrollBy(300, 0);
};
nextBtn[index].addEventListener('click', e => {
nextCarousel();
});
//Prev Carousel
const prevCarousel = () => {
if(carsouselImages[0]) {
carousel.scrollTo(4800,0);
}
carousel.scrollBy(-300, 0);
};
prevBtn[index].addEventListener('click', e => {
prevCarousel();
});
// Auto carousel
const auto = true; // Auto scroll
const intervalTime = 5000;
let sliderInterval;
if (auto) {
sliderInterval = setInterval(nextCarousel, intervalTime);
};
carousel.addEventListener('mouseover', (stopInterval) => {
clearInterval(sliderInterval);
});
carousel.addEventListener('mouseleave', (startInterval) => {
if (auto) {
sliderInterval = setInterval(nextCarousel, intervalTime);
}
});
//for mobile events
carousel.addEventListener('touchstart', (stopIntervalT) => {
clearInterval(sliderInterval);
});
carousel.addEventListener('touchend', (startIntervalT) => {
if (auto) {
sliderInterval = setInterval(nextCarousel, intervalTime);
}
});
//Debounce
var previousCall;
window.addEventListener('resize', () => {
if (previousCall >= 0) {
clearTimeout(previousCall);
}
});
});
Here are css and html codes if needed:
/** img-carousel **/
#imgages-carousel {
display: grid;
align-items: center;
justify-items: center;
padding: 40px 0px;
}
#imgages-carousel1 {
display: grid;
align-items: center;
justify-items: center;
padding: 40px 0px;
}
.img-carousel-container {
width: 800px;
position: relative;
}
.img-carousel {
display: flex;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-bottom: 5px;
}
.img-carousel div {
flex: none;
scroll-snap-align: start;
width: 800px;
position: relative;
}
.img-carousel div img {
display: block;
width: 100%;
object-fit: cover;
}
.img-carousel div p {
position: absolute;
top: 0;
right: 10px;
background: rgba(0,0,0,0.5);
color: #fff;
padding: 5px;
border-radius: 10px;
}
.img-carousel-container button {
position: absolute;
top: calc(50% - 15px);
transform: translateY(-50%);
border: none;
background-color: rgba(255, 193, 7, 0.7);
color: #000;
cursor: pointer;
padding: 10px 15px;
border-radius: 50%;
outline: none;
opacity: 0;
transition: all ease-in-out 0.5s;
}
.prev {
left: 10px;
}
.next {
right: 10px;
}
.img-carousel-container:hover button {
opacity: 1;
}
.img-carousel-container button:hover {
background-color: #ffc107;
}
/** custom scrollbar **/
.img-carousel::-webkit-scrollbar {
width: 10px;
height: 10px;
}
.img-carousel::-webkit-scrollbar-thumb {
background: #ffc107;
border-radius: 10px;
}
.img-carousel::-webkit-scrollbar-track {
background: transparent;
}
.img-carousel-container:hover .img-carousel::-webkit-scrollbar-thumb {
visibility: visible;
}
#media screen and (max-width: 800px) {
.img-carousel-container {
width: 100%;
}
.img-carousel div {
width: 100%;
}
}
html:
<!-- section images carousel -->
<section id="imgages-carousel">
<div class="img-carousel-container">
<div class="img-carousel">
<div>
<img src="https://source.unsplash.com/9Nok_iZEgLk/800x450">
<p>1/6</p>
</div>
<div>
<img src="https://source.unsplash.com/4v7ubW7jz1Q/800x450">
<p>2/6</p>
</div>
<div>
<img src="https://source.unsplash.com/rtCujH697DU/800x450">
<p>3/6</p>
</div>
<div>
<img src="https://source.unsplash.com/ELv8fvulR0g/800x450">
<p>4/6</p>
</div>
<div>
<img src="https://source.unsplash.com/LoPGu6By90k/800x450">
<p>5/6</p>
</div>
<div>
<img src="https://source.unsplash.com/Ndz3w6MCeWc/800x450">
<p>6/6</p>
</div>
</div>
<button class="prev"><i class="fas fa-chevron-left fa-2x"></i></button>
<button class="next"><i class="fas fa-chevron-right fa-2x"></i></button>
</div>
</section>
<section id="imgages-carousel1">
<div class="img-carousel-container">
<div class="img-carousel">
<div>
<img src="https://source.unsplash.com/9Nok_iZEgLk/800x450">
<p>1/6</p>
</div>
<div>
<img src="https://source.unsplash.com/4v7ubW7jz1Q/800x450">
<p>2/6</p>
</div>
<div>
<img src="https://source.unsplash.com/rtCujH697DU/800x450">
<p>3/6</p>
</div>
<div>
<img src="https://source.unsplash.com/ELv8fvulR0g/800x450">
<p>4/6</p>
</div>
<div>
<img src="https://source.unsplash.com/LoPGu6By90k/800x450">
<p>5/6</p>
</div>
<div>
<img src="https://source.unsplash.com/Ndz3w6MCeWc/800x450">
<p>6/6</p>
</div>
</div>
<button class="prev"><i class="fas fa-chevron-left fa-2x "></i></button>
<button class="next"><i class="fas fa-chevron-right fa-2x "></i></button>
</div>
</section>

Javascript - subdivided nav opens and close the main one

I need the country tab to remain, when the sites expends. I think a forEach loop is causing issues and I am not sure how to adress this, any help is greatly appreciated. I have data to display for over 50 countries and once the function works, my "country" tab will be Copy/pasted, I thought of using hard coded ID but its gonna take forever :(
HTML
<li class="country"><div class="list_container">
<button class="country_name">Algeria</button>
<ul class="site_list">
<div class="site_container">
<li class="site">Bejaja</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
<div class="site_container">
<li class="site">Constantine</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
<div class="site_container">
<li class="site">Jijel</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
<div class="site_container">
<li class="site">Setif</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
</ul>
</div>
</li>
JS
const country = document.querySelectorAll('.list_container');
// country selection
country.forEach((item) => {
const btn = item.querySelector('.country_name');
btn.addEventListener('click', () => {
country.forEach((site) => {
if(site !== item) {
site.classList.remove('show_sites')
}
})
item.classList.toggle('show_sites')
})
})
// site selection
const siteGroup = document.querySelectorAll('.site_container');
siteGroup.forEach((item) => {
console.log(item);
siteBtn = item.querySelector('.site_link');
console.log(siteBtn)
siteBtn.addEventListener('click', () => {
siteGroup.forEach(site => {
console.log(site)
if(site !== item) {
site.classList.remove('display_site')
}
})
item.classList.toggle('display_site')
})
})```
CSS
.country_list {
height: 100%;
width: 100%;
margin: 0;
padding: 1em;
}
.country {
list-style-type: none;
padding: 0em;
margin: 0.5em;
}
.country_name {
text-decoration:none;
background-color: rgba(114, 114,114, 0.5);
padding: 0.3em 1em;
color: white;
border-radius: 15px;
z-index: 3;
position: relative;
}
.list_container {
height: 2em;
width: 80%;;
overflow: hidden;
}
.site_list {
list-style-type: none;
background-color: rgba(255,255,255, 0.5);
border-radius: 5px;
width: 50em;
z-index: 4;
padding: 0.3em;
overflow: hidden;
}
.site_container {
height: 1.3em;
overflow: hidden;
}
.display_site {
height: 3.5em;
}
.site {
padding: 0.2em;
}
.show_sites {
height: 30em;
}

click outside burger menu to close using javascript

I have been making a burger menu that works on desktop, opens and closes with an event listener.
It works fine but then i wanted to make it so that if the use clicked outside of the burger menu it also closes the menu.
I found a bit of java script that uses some logic to say that if not the navigation then close menu. it works when you click outside the menu but then the problem is that the toggle stops closing the menu.
I split my code up into two sections.
The first code block is the code working with the toggle.
The second block is the code that i'm using to try and make the click outside the menu work.
I think i have been staring at this for to long and cant seem to find a solution.
thanks in advance for any help.
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<style>
a{
color: #fff;
}
.ic-burger{
width: 50px;
height: 50px;
background: #000;
display: block;
position: relative;
z-index: 10;
}
.ic-nav ul {
list-style: none;
padding-left: 0px;
display: flex;
flex-direction: column;
right: 0px;
top: 0px;
height: 100%;
position: fixed;
z-index: 5;
overflow: auto;
margin: 0px;
padding-left: 20px;
padding-right: 20px;
}
html.ic-show .ic-nav:before{
content: '';
position: absolute;
top: 0;
left: auto;
right: 0;
bottom: 0;
background-color: rgba(18,18,18,0.7);
z-index: 1;
width: 100%
}
.ic-second-level{
opacity: 0;
visibility: hidden;
transition: all 200ms linear;
padding: 0px;
padding-top: 100px;
background: #1e1e1e;
}
html.ic-show .ic-second-level{
opacity: 1;
visibility: visible;
}
</style>
<nav class="ic-nav">
<!-- <div class="ic-burger-bkg"> -->
<ul class="ic-burger-container">
<li>
<a href="javascript:void(0);" class="ic-burger" aria-expanded="false" aria-controls="menu" id="burger-icon">
<div class="nav-icon">
Burger <br>toggle
</div>
</a>
<!-- ############ -->
<ul class="ic-second-level" role="region" id="menu" aria-labeledby="burger-icon">
<li class="top-li">
About
</li>
<li class="top-li">
News
</li>
<li class="top-li">
Team
</li>
<li class="top-li">
Contact
</li>
</ul>
<!-- ############ -->
</li>
</ul>
<!-- </div> -->
</nav>
</body>
<script>
var documentElement = document.querySelector("html");
var sidebarIsOpen = () => documentElement.classList.contains("ic-show");
var openSidebar = () => {
documentElement.classList.add("ic-show");
};
var closeSidebar = () => {
documentElement.classList.remove("ic-show");
};
document.querySelector('.ic-burger').addEventListener("click", function() {
sidebarIsOpen() ? closeSidebar() : openSidebar();
});
</script>
</html>
Here is the second bit of code i cant get to play friendly with the first.
let sidebar = document.querySelector(".ic-second-level");
document.addEventListener("mouseup", function(event){
// If the event didn't originate from the open button or the sidebar, close it
if(event.target !== sidebar && event.target !== openSidebar){
closeSidebar();
}
});
these are the two sources ive used to help me
https://dev.to/tongrhj/the-mistake-developers-make-when-coding-a-hamburger-menu-1deg
Click Outside To close slide menu Javascript
I am using event delegation to check if you click on the "ic-nav" element and then close it. Works like charm.
document.addEventListener('click',function(e){
if(e.target && e.target.classList == 'ic-nav'){
sidebarIsOpen() ? closeSidebar() : openSidebar();
}
});
var documentElement = document.querySelector("html");
var sidebarIsOpen = () => documentElement.classList.contains("ic-show");
var openSidebar = () => {
documentElement.classList.add("ic-show");
};
var closeSidebar = () => {
documentElement.classList.remove("ic-show");
};
document.querySelector('.ic-burger').addEventListener("click", function() {
sidebarIsOpen() ? closeSidebar() : openSidebar();
});
document.addEventListener('click',function(e){
if(e.target && e.target.classList == 'ic-nav'){
sidebarIsOpen() ? closeSidebar() : openSidebar();
}
});
a{
color: #fff;
}
.ic-burger{
width: 50px;
height: 50px;
background: #000;
display: block;
position: relative;
z-index: 10;
}
.ic-nav ul {
list-style: none;
padding-left: 0px;
display: flex;
flex-direction: column;
right: 0px;
top: 0px;
height: 100%;
position: fixed;
z-index: 5;
overflow: auto;
margin: 0px;
padding-left: 20px;
padding-right: 20px;
}
html.ic-show .ic-nav:before{
content: '';
position: absolute;
top: 0;
left: auto;
right: 0;
bottom: 0;
background-color: rgba(18,18,18,0.7);
z-index: 1;
width: 100%
}
.ic-second-level{
opacity: 0;
visibility: hidden;
transition: all 200ms linear;
padding: 0px;
padding-top: 100px;
background: #1e1e1e;
}
html.ic-show .ic-second-level{
opacity: 1;
visibility: visible;
}
<nav class="ic-nav">
<!-- <div class="ic-burger-bkg"> -->
<ul class="ic-burger-container">
<li>
<a href="javascript:void(0);" class="ic-burger" aria-expanded="false" aria-controls="menu" id="burger-icon">
<div class="nav-icon">
Burger <br>toggle
</div>
</a>
<!-- ############ -->
<ul class="ic-second-level" role="region" id="menu" aria-labeledby="burger-icon">
<li class="top-li">
About
</li>
<li class="top-li">
News
</li>
<li class="top-li">
Team
</li>
<li class="top-li">
Contact
</li>
</ul>
<!-- ############ -->
</li>
</ul>
<!-- </div> -->
</nav>

HTML Select item show div and post problem

I am confused. I want two products to be selected. These products will be open by clicking the button. The selection will be made on the screen that opens. And the selected product will replace the button clicked.
I can show the products by clicking the button. I even got the result I wanted as text with jquery. But I used <select> <option> for this. There will be no drop-down list and only one will be selected. The selected image will replace the clicked area. I couldn't :(
$(document).ready(function() {
$(".showbutton, .showbutton img").click(function(event) {
var buttonName = $(this).closest('div').attr('id');
var buttonNo = buttonName.slice(4);
var boxName = "#box" + buttonNo;
$(boxName).fadeIn(300);
});
$(".closebtn").click(function() {
$(".box").fadeOut(200);
});
$(".box").click(function() {
$(".box").fadeOut(200);
});
$(".innerbox").click(function() {
event.preventDefault();
event.stopPropagation();
});
});
div.showbutton {}
div.showbutton:hover {}
.box {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.innerbox {
overflow: scroll;
width: 80%;
height: 80%;
margin: 5% auto;
background-color: white;
border: 3px solid gray;
padding: 10px;
box-shadow: -10px -10px 25px #ccc;
}
#box1 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
#box2 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
.closebutton {
width: 20%;
float: right;
cursor: pointer;
}
.closebtn {
text-align: right;
font-size: 20px;
font-weight: bold;
}
.clear {
clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="builder" action="" method="POST">
<div class="showbutton" id="link1">
click for first items
</div>
<div id="box1" class="box">
<div class="innerbox">
<div class="closebutton">
<div class="closebtn">X</div>
</div>
- item1.png - item2.png - item3.png
</div>
</div>
<div class="showbutton" id="link1">
click for second items
</div>
<div id="box1" class="box">
<div class="innerbox">
<div class="closebutton">
<div class="closebtn">X</div>
</div>
- item1.png - item2.png - item3.png
</div>
</div>
JSFIDDLE example of my codes: https://jsfiddle.net/j5fqhat6/
You can add data attribute to your kutu div this will help us to identify from where click event has been occurred .So, whenever your gosterButonu is been clicked you can use this data-id to add selected images text to your gosterButonu div.
Demo Code :
$(document).ready(function() {
$(".gosterButonu, .gosterButonu img").click(function(event) {
var butonAdi = $(this).attr('id');
console.log(butonAdi)
//if on click of button you want to remove active class
// $("div[data-id="+butonAdi+"]").find("li").removeClass("active")
$("div[data-id=" + butonAdi + "]").fadeIn(300);
});
$(".kapatButonu").click(function() {
var data_id = $(this).closest(".kutu").data("id");
$("#" + data_id).text($(this).closest(".icKutu").find("li.active").text())
$(".kutu").fadeOut(200);
});
$(".kutu").click(function() {
$(".kutu").fadeOut(200);
});
$(".icKutu").click(function() {
event.preventDefault();
event.stopPropagation();
});
//on click of li
$(".images li").click(function() {
//remove active class from other lis
$(this).closest(".images").find("li").not(this).removeClass("active")
//add active class to li which is clicked
$(this).addClass("active");
})
});
div.gosterButonu {}
div.gosterButonu:hover {}
.kutu {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.icKutu {
overflow: scroll;
width: 80%;
height: 80%;
margin: 5% auto;
background-color: white;
border: 3px solid gray;
padding: 10px;
box-shadow: -10px -10px 25px #ccc;
}
#kutu1 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
#kutu2 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
.kapatButonuCerceve {
width: 20%;
float: right;
cursor: pointer;
}
.kapatButonu {
text-align: right;
font-size: 20px;
font-weight: bold;
}
.clear {
clear: both;
}
ul li {
list-style-type: none
}
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="builder" action="" method="POST">
<div class="gosterButonu" id="link1">
clickfor first items
</div>
<!--added data-id which matched with the div above-->
<div id="kutu1" data-id="link1" class="kutu">
<div class="icKutu">
<div class="kapatButonuCerceve">
<div class="kapatButonu">X</div>
</div>
<div class="clear"></div>
<!--added ul li-->
<ul class="images">
<li>- item1.png</li>
<li> - item2.png </li>
<li>- item3.png</li>
</ul>
</div>
</div>
<div class="gosterButonu" id="link2">
click for second items
</div>
<!--added data-id which matched with the div above-->
<div id="kutu2" data-id="link2" class="kutu">
<div class="icKutu">
<div class="kapatButonuCerceve">
<div class="kapatButonu">X</div>
</div>
<div class="clear"></div>
<ul class="images">
<li>- item1.png</li>
<li> - item2.png </li>
<li>- item3.png</li>
</ul>
</div>
</div>

Categories

Resources