how come drillmenu doesn't work and the screens overlap? - javascript

I have a problem with the code of this drillmenu. When I click on the "click" button the menu overlaps and the other screen items appear.
I have to add many other buttons and submenus, but in this way I will never be able to do it. I was inspired by a menu on the web, but I just can't!
enter code here
<div class="wrapper">
<ul data-drilldown>
<li><a data-drilldown-item href="#">Home</a></li>
<li><a href="#" data-drilldown-button>Contact ➤
<ul data-drilldown-sub>
<a href="#" data-drilldown-back>← Back</a>
<li>house</li>
<li><a href="#" data-drilldown-button-2>More ➤
<ul data-drilldown-sub-2>
<a href="#" data-drilldown-back-2>← Back</a>
<li><a href="">personal</a></li>
</ul>
</a> </li>
</ul>
</a> </li>
<li><a href="#" data-drilldown-button>click ➤
<ul data-drilldown-sub>
<a href="#" data-drilldown-back>← Back</a>
<li><a href="#">mouse/a></li>
<li><a href="#" data-drilldown-button-2>explor ➤
<ul data-drilldown-sub-2>
<a href="#" data-drilldown-back-2>← Back</a>
<li><a href="">mypc</a></li>
</ul>
</a> </li>
</ul>
</a> </li>
</ul>
</div>
<style>
[data-drilldown] a { color: #555; }
[data-drilldown] a:hover {
color: #ff77aa;
-webkit-transition: all .1s;
transition: all .1s;
}
.wrapper {
display: block;
width: 330px;
height: auto;
border: 1px solid #ccc;
margin: 50px auto;
padding: 10px 15px;
border-radius: 5px;
position: relative;
overflow: hidden;
}
[data-drilldown] {
font-size: 17px;
-webkit-transition: all .2s;
transition: all .2s;
}
[data-drilldown] li { padding: 5px 0px; }
[data-drilldown-sub] {
position: absolute;
display: block;
width: 330px;
top: 0;
left: 100%;
padding: 10px 15px;
-webkit-transition: all .2s;
transition: all .2s;
}
[data-drilldown-item] {
position: relative;
left: 0;
-webkit-transition: all .2s;
transition: all .2s;
}
[data-drilldown-button] {
position: relative;
left: 0;
-webkit-transition: all .2s;
transition: all .2s;
}
[data-drilldown-button-2] {
position: relative;
left: 0;
-webkit-transition: all .2s;
transition: all .2s;
}
[data-drilldown-sub-2] {
position: absolute;
display: block;
width: 330px;
top: 0;
left: 100%;
padding: 10px 15px;
-webkit-transition: all .2s;
transition: all .2s;
}
[data-drilldown-back], [data-drilldown-back-2] {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
display: block;
margin-bottom: 10px;
}
.open {
left: 0;
visibility: visible;
}
.open-sub-2 {
left: 100%;
visibility: visible;
}
.close {
left: -100%;
visibility: hidden;
}
li {
list-style-type: none;
}
</style>
<script src="//code.jquery.com/jquery-3.2.0.min.js"></script>
<script>
$("[data-drilldown-button]").click(function() {
$('[data-drilldown-sub]').addClass("open");
$("[data-drilldown-item], [data-drilldown-button]").addClass("close");
$(".wrapper").css("height", $('[data-drilldown-sub]').outerHeight())
return false;
});
$("[data-drilldown-back]").click(function() {
$('[data-drilldown-sub]').removeClass("open");
$("[data-drilldown-item], [data-drilldown-button]").removeClass("close");
$(".wrapper").css("height", "auto");
return false;
});
$("[data-drilldown-button-2]").click(function() {
$('[data-drilldown-sub-2]').addClass("open-sub-2");
$("[data-drilldown-sub], [data-drilldown-button-2]").addClass("close");
$(".wrapper").css("height", $('[data-drilldown-sub-2]').outerHeight());
return false;
});
$("[data-drilldown-back-2]").click(function() {
$('[data-drilldown-sub-2]').removeClass("open-sub-2");
$("[data-drilldown-sub], [data-drilldown-button-2]").removeClass("close");
$(".wrapper").css("height", $('[data-drilldown-sub]').outerHeight());
return false;
});
</script>

Related

When my elements have flex-direction: column they no longer have transitions

I have three buttons, each with their dropdown menu which is toggled on click. The dropdown menu has a transition of transition: all 0.2s and it works just fine when they are displayed as flex-direction: row. Now I have a media query that displays them with flex-direction: column and for some reason they no longer have transitions.
const buttons = document.querySelectorAll('.link');
let arrow = document.querySelectorAll('.arrow-pag');
let dropMenu = document.querySelectorAll('.link-dropdown');
Array.from(buttons).forEach((el, index) => {
let toggled = false;
el.addEventListener('click', function(event) {
if (toggled) {
el.style.backgroundColor = "white";
el.style.color = "var(--midnightBlue)";
arrow[index].style.borderColor = "var(--midnightBlue)";
arrow[index].classList.toggle('up-pag');
dropMenu[index].style.height = "0px";
toggled = false;
} else {
console.log(index);
el.style.backgroundColor = "var(--midnightBlue)";
el.style.color = "white";
arrow[index].style.borderColor = "white";
arrow[index].classList.toggle('up-pag');
dropMenu[index].style.height = "100%";
toggled = true;
}
});
});
:root {
--fontSansSerif: 'Inter';
--fontSerif: 'DM Serif Display';
--heightDropdown: 250px;
--bluePigment: #333895;
--midnightBlue: #1B1164;
--aliceBlue: #E4EBF8;
--lightSteelBlue: #B0C5E3;
--darkSteelBlue: #86ADE3;
}
.pagini-folositoare,
.toate-linkurile {
width: 100%;
}
.toate-linkurile {
font-weight: 500;
display: flex;
gap: 30px;
}
.link {
box-shadow: 0 3px 7px 2px rgba(0, 0, 0, 0.1);
width: 100%;
padding: 20px 10px;
background-color: white;
border-color: var(--midnightBlue);
transition: all 0.15s;
}
.link:hover {
cursor: pointer;
}
.link-container {
width: 33%;
}
.link h2 {
user-select: none;
margin: 0;
font-weight: 500;
text-align: center;
}
.arrow-pag {
vertical-align: middle;
border: solid;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
margin-bottom: 9px;
margin-left: 10px;
}
.down-pag {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transition: all 0.15s;
}
.up-pag {
margin-bottom: 4px;
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
}
.link-dropdown {
background-color: white;
box-shadow: 0 3px 7px 2px rgba(0, 0, 0, 0.1);
padding: 0px 10px;
height: 0px;
overflow: hidden;
transition: all 0.2s;
}
.link-dropdown ul {
margin: 0px;
padding-left: 15px;
}
.link-dropdown ul li {
margin-bottom: 10px;
}
#media all and (max-width: 790px) {
.toate-linkurile {
flex-direction: column;
}
.link-container {
width: 100%;
transition: all 0.2s;
}
.link {
width: 100%;
transition: all 0.2s;
}
}
<div class="pagini-folositoare">
<h1>Pagini folositoare</h1>
<div class="toate-linkurile">
<div class="link-container">
<div class="link">
<h2>MEDIA<i class="arrow-pag down-pag"></i></h2>
</div>
<div class="link-dropdown height">
<ul>
<li><a target="_blank" href="https://stackoverflow.com">aaaa</a></li>
<li><a target="_blank" href="https://stackoverflow.com">bbbbb</a></li>
<li><a target="_blank" href="https://stackoverflow.com">cccc</a></li>
</ul>
</div>
</div>
<div class="link-container">
<div class="link">
<h2>CLUBURI<i class="arrow-pag down-pag"></i></h2>
</div>
<div class="link-dropdown height">
<ul>
<li><a target="_blank" href="https://stackoverflow.com">link 1</a></li>
<li><a target="_blank" href="https://stackoverflow.com">link 2</a></li>
<li><a target="_blank" href="https://stackoverflow.com">link 3</a></li>
</ul>
</div>
</div>
<div class="link-container">
<div class="link">
<h2>ADMITERE<i class="arrow-pag down-pag"></i></h2>
</div>
<div class="link-dropdown">
<ul>
<li><a target="_blank" href="https://stackoverflow.com">aaaa</a></li>
<li><a target="_blank" href="https://stackoverflow.com">bbbbb</a></li>
<li><a target="_blank" href="https://stackoverflow.com">cccccc</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
Now I don't know if I did something wrong in my code or if I'm missing a transition somewhere, but I can't figure this out
I think this is because when in flex-direction: column, the height of each link-container item need to be specified for a transition of height to work.
Since this does not seem practical in this use case, you could use flex-wrap: wrap instead of flex-direction: column.
#media all and (max-width: 790px) {
.toate-linkurile {
flex-wrap: wrap;
}
}
This will make the transition of .link-dropdown happen, which hopefully achieves the desired result without major changes of the existing code.
Full example:
const buttons = document.querySelectorAll(".link");
let arrow = document.querySelectorAll(".arrow-pag");
let dropMenu = document.querySelectorAll(".link-dropdown");
Array.from(buttons).forEach((el, index) => {
let toggled = false;
el.addEventListener("click", function (event) {
if (toggled) {
el.style.backgroundColor = "white";
el.style.color = "var(--midnightBlue)";
arrow[index].style.borderColor = "var(--midnightBlue)";
arrow[index].classList.toggle("up-pag");
dropMenu[index].style.height = "0px";
toggled = false;
} else {
console.log(index);
el.style.backgroundColor = "var(--midnightBlue)";
el.style.color = "white";
arrow[index].style.borderColor = "white";
arrow[index].classList.toggle("up-pag");
dropMenu[index].style.height = "100%";
toggled = true;
}
});
});
:root {
--fontSansSerif: "Inter";
--fontSerif: "DM Serif Display";
--heightDropdown: 250px;
--bluePigment: #333895;
--midnightBlue: #1b1164;
--aliceBlue: #e4ebf8;
--lightSteelBlue: #b0c5e3;
--darkSteelBlue: #86ade3;
}
.pagini-folositoare,
.toate-linkurile {
width: 100%;
}
.toate-linkurile {
font-weight: 500;
display: flex;
gap: 30px;
}
.link {
box-shadow: 0 3px 7px 2px rgba(0, 0, 0, 0.1);
width: 100%;
padding: 20px 10px;
background-color: white;
border-color: var(--midnightBlue);
transition: all 0.15s;
}
.link:hover {
cursor: pointer;
}
.link-container {
width: 33%;
}
.link h2 {
user-select: none;
margin: 0;
font-weight: 500;
text-align: center;
}
.arrow-pag {
vertical-align: middle;
border: solid;
border-width: 0 3px 3px 0;
display: inline-block;
padding: 3px;
margin-bottom: 9px;
margin-left: 10px;
}
.down-pag {
transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transition: all 0.15s;
}
.up-pag {
margin-bottom: 4px;
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
}
.link-dropdown {
background-color: white;
box-shadow: 0 3px 7px 2px rgba(0, 0, 0, 0.1);
padding: 0px 10px;
height: 0px;
overflow: hidden;
transition: all 0.2s;
}
.link-dropdown ul {
margin: 0px;
padding-left: 15px;
}
.link-dropdown ul li {
margin-bottom: 10px;
}
#media all and (max-width: 790px) {
.toate-linkurile {
flex-wrap: wrap;
}
.link-container {
width: 100%;
transition: all 0.2s;
}
.link {
width: 100%;
transition: all 0.2s;
}
}
<div class="pagini-folositoare">
<h1>Pagini folositoare</h1>
<div class="toate-linkurile">
<div class="link-container">
<div class="link">
<h2>MEDIA<i class="arrow-pag down-pag"></i></h2>
</div>
<div class="link-dropdown height">
<ul>
<li><a target="_blank" href="https://stackoverflow.com">aaaa</a></li>
<li><a target="_blank" href="https://stackoverflow.com">bbbbb</a></li>
<li><a target="_blank" href="https://stackoverflow.com">cccc</a></li>
</ul>
</div>
</div>
<div class="link-container">
<div class="link">
<h2>CLUBURI<i class="arrow-pag down-pag"></i></h2>
</div>
<div class="link-dropdown height">
<ul>
<li>
<a target="_blank" href="https://stackoverflow.com">link 1</a>
</li>
<li>
<a target="_blank" href="https://stackoverflow.com">link 2</a>
</li>
<li>
<a target="_blank" href="https://stackoverflow.com">link 3</a>
</li>
</ul>
</div>
</div>
<div class="link-container">
<div class="link">
<h2>ADMITERE<i class="arrow-pag down-pag"></i></h2>
</div>
<div class="link-dropdown">
<ul>
<li><a target="_blank" href="https://stackoverflow.com">aaaa</a></li>
<li><a target="_blank" href="https://stackoverflow.com">bbbbb</a></li>
<li>
<a target="_blank" href="https://stackoverflow.com">cccccc</a>
</li>
</ul>
</div>
</div>
</div>
</div>

Scrolling div/section with indicators

I want to create a vertical scrolling div with an active indicators. However I'm having trouble with it event firing on the div targeted. I set it to window.addEventListener it works fine at full height of the window but if I set it to div.addEventListener it's not firing inside of the element at all. I'm Hoping someone has some pointer for this. Here's what I got so far.
section.scroller {
max-width: 900px;
margin: auto;
background: antiquewhite;
scroll-behavior: smooth;
position: relative;
width: 100%;
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
padding-right: 17px;
// padding: 0 17px;
box-sizing: content-box;
}
.sec {
min-height: 100vh;
// width: 100vw;
display: flex;
align-items: center;
justify-content: center;
scroll-behavior: smooth;
// width: 100%;
&:nth-child(odd) {
background: #ddd;
}
}
.lnbNavbar {
top: 50%;
transform: translateY(-50%);
margin: 0;
padding: 0;
border-radius: 15px;
transition: opacity .4s ease .2s;
opacity: 0;
position: relative;
float: right;
transition: .3s all;
ul {
list-style: none;
padding: 0;
margin: 0;
li {
width: 0px;
position: relative;
text-align: right;
.dot {
border: 2px solid#333;
width: 10px;
height: 10px;
display: inline-block;
border-radius: 50%;
transition: .2s ease;
span {
display: inline-block;
}
}
}
}
}
.lnbNavbar ul li a:active,
.lnbNavbar ul li a:hover {
border-color: rgb(124, 7, 7);
background-color: gray;
transform: scale(1.8);
}
.lnbNavbar ul li.active a,
.lnbNavbar ul li:hover a {
border-color: rgb(124, 7, 7);
background-color: gray;
transform: scale(1.8);
}
.outter {
width: 800px;
height: 500px;
margin: auto;
overflow: hidden;
}
<div class="outter" id="outter">
<section class="scroller" id="scroller">
<nav class="lnbNavbar">
<ul>
<li class="home active">
<a href="#home" class=" home dot">
<span></span>
</a>
</li>
<li class="about">
<a href="#about" class="about dot">
<span></span>
</a>
</li>
<li class="service">
<a href="#service" class="service dot">
<span></span>
</a>
</li>
<li class="project">
<a href="#project" class="project dot">
<span></span>
</a>
</li>
<li class="contact">
<a href="#contact" class="contact dot">
<span></span>
</a>
</li>
</ul>
</nav>
<section class="sec" id="about"><h4>about</h4></section>
<section class="sec" id="service"><h4>service</h4></section>
<section class="sec" id="project"><h4>project</h4></section>
<section class="sec" id="contact"><h4>contact</h4></section>
<section class="sec" id="home"><h4>home</h4></section>
</section>
<script>
const sections = document.querySelectorAll('section');
const navLi = document.querySelectorAll('.lnbNavbar ul li');
const div = document.getElementById("outter")[0];
div.addEventListener('scroll', ()=> {
let current = '';
sections.forEach( section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if(pageYOffset >= (sectionTop - sectionHeight / 4)){
current = section.getAttribute('id');
}
})
console.log(current);
navLi.forEach( li => {
li.classList.remove('active');
if(li.classList.contains(current)){
li.classList.add('active')
}
})
})
</script>
</div>

Close javascript menu when click on item or lost focus

I'm trying to customise a menu I've found on CodePen. Here's what I've found.
What I'm trying to do is modify it so that the menu closes after you click on an item, or if you click outside the menu. I've tried various things but can't seem to get it to work.
Here's my html:
<!-- new hamburger menu be here -->
<div id="menu-main">
<div id="menu-wrapper">
<div id="hamburger-menu"><span></span><span></span><span></span></div>
<!-- hamburger-menu -->
</div>
<!-- menu-wrapper -->
<ul class="menu-list accordion">
<li id="nav1">
<a class="menu-link" href="index.html">Home</a>
</li>
<li id="nav2">
<a class="menu-link" href="#about">About the Project</a>
</li>
<li id="nav3">
<a class="menu-link" href="#timeline">Timeline</a>
</li>
<li id="nav4">
<a class="menu-link" href="#vision">The Vision</a>
</li>
<li id="nav5">
<a class="menu-link" href="#where">Where We Are</a>
</li>
<li id="nav6">
<a class="menu-link" href="#news">Stay In Touch</a>
</li>
<li id="nav7">
<a class="menu-link" href="#faq">FAQ</a>
</ul>
</div>
Here's my JavaScript
$(function() {
function slideMenu() {
var activeState = $("#menu-main .menu-list").hasClass("active");
$("#menu-main .menu-list").animate({left: activeState ? "0%" : "-100%"}, 400);
}
$("#menu-wrapper").click(function(event) {
event.stopPropagation();
$("#hamburger-menu").toggleClass("open");
$("#menu-main .menu-list").toggleClass("active");
slideMenu();
$("body").toggleClass("overflow-hidden");
});
$(".menu-list").find(".accordion-toggle").click(function() {
$(this).next().toggleClass("open").slideToggle("fast");
$(this).toggleClass("active-tab").find(".menu-link").toggleClass("active");
$(".menu-list .accordion-content").not($(this).next()).slideUp("fast").removeClass("open");
$(".menu-list .accordion-toggle").not(jQuery(this)).removeClass("active-tab").find(".menu-link").removeClass("active");
});
}); // jQuery load
I've tried adding in various classes in this bit as I believe this is what controls the code but no luck:
$(".menu-list").find(".accordion-toggle").click(function() {
$(this).next().toggleClass("open").slideToggle("fast");
$(this).toggleClass("active-tab").find(".menu-link").toggleClass("active");
$(".menu-list .accordion-content").not($(this).next()).slideUp("fast").removeClass("open");
$(".menu-list .accordion-toggle").not(jQuery(this)).removeClass("active-tab").find(".menu-link").removeClass("active");
});
Would love some help with this.
You can add a check on document click to see if an element has been clicked our the user clicked outside the menu div.
$(function() {
function slideMenu() {
var activeState = $("#menu-container .menu-list").hasClass("active");
$("#menu-container .menu-list").animate({
left: activeState ? "0%" : "-100%"
}, 400);
}
$("#menu-wrapper").click(function(event) {
event.stopPropagation();
$("#hamburger-menu").toggleClass("open");
$("#menu-container .menu-list").toggleClass("active");
slideMenu();
$("body").toggleClass("overflow-hidden");
});
$(".menu-list").find(".accordion-toggle").click(function() {
$(this).next().toggleClass("open").slideToggle("fast");
$(this).toggleClass("active-tab").find(".menu-link").toggleClass("active");
$(".menu-list .accordion-content").not($(this).next()).slideUp("fast").removeClass("open");
$(".menu-list .accordion-toggle").not(jQuery(this)).removeClass("active-tab").find(".menu-link").removeClass("active");
});
$(document).on("click", function(e) {
let isLink = jQuery(e.target).is(".accordion-content a");
let isOutside = jQuery(e.target).closest("#menu-container").length == 0;
if (isLink || isOutside)
$("#menu-wrapper").trigger("click");
})
}); // jQuery load
ul {
list-style: none;
}
a {
text-decoration: none;
color: black;
}
body {
font-family: 'Dosis', sans-serif;
background: #FF5722;
}
#menu-wrapper {
overflow: hidden;
max-width: 100%;
cursor: pointer;
}
#menu-wrapper #hamburger-menu {
position: relative;
width: 25px;
height: 20px;
margin: 15px;
}
#menu-wrapper #hamburger-menu span {
opacity: 1;
left: 0;
display: block;
width: 100%;
height: 2px;
border-radius: 10px;
color: black;
background-color: white;
position: absolute;
transform: rotate(0deg);
transition: .4s ease-in-out;
}
#menu-wrapper #hamburger-menu span:nth-child(1) {
top: 0;
}
#menu-wrapper #hamburger-menu span:nth-child(2) {
top: 9px;
}
#menu-wrapper #hamburger-menu span:nth-child(3) {
top: 18px;
}
#menu-wrapper #hamburger-menu.open span:nth-child(1) {
transform: translateY(9px) rotate(135deg);
}
#menu-wrapper #hamburger-menu.open span:nth-child(2) {
opacity: 0;
transform: translateX(-60px);
}
#menu-wrapper #hamburger-menu.open span:nth-child(3) {
transform: translateY(-9px) rotate(-135deg);
}
#menu-container .menu-list .menu-submenu {
padding-top: 20px;
padding-bottom: 20px;
}
#menu-container .menu-list {
padding-left: 0;
display: block;
position: absolute;
width: 100%;
max-width: 450px;
background: white;
box-shadow: rgba(100, 100, 100, 0.2) 6px 2px 10px;
z-index: 999;
overflow-y: auto;
overflow-x: hidden;
left: -100%;
}
#menu-container .menu-list li.accordion-toggle,
#menu-container .menu-list .menu-login {
font-size: 16px;
padding: 20px;
text-transform: uppercase;
border-top: 1px solid #dbdcd2;
}
#menu-container .menu-list li:first-of-type {
border-top: 0;
}
.accordion-toggle,
.accordion-content {
cursor: pointer;
font-size: 16px;
position: relative;
letter-spacing: 1px;
}
.accordion-content {
display: none;
}
.accordion-toggle a:before,
.accordion-toggle a:after {
content: '';
display: block;
position: absolute;
top: 50%;
right: 30px;
width: 15px;
height: 2px;
margin-top: -1px;
background-color: #5a5858;
transform-origin: 50% 50%;
transition: all 0.3s ease-out;
}
.accordion-toggle a:before {
transform: rotate(-90deg);
opacity: 1;
z-index: 2;
}
.accordion-toggle.active-tab {
background: yellowgreen;
transition: all 0.3s ease;
}
.accordion-toggle a.active:before {
transform: rotate(0deg);
background: #fff !important;
}
.accordion-toggle a.active:after {
transform: rotate(180deg);
background: #fff !important;
opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="menu-container">
<div id="menu-wrapper">
<div id="hamburger-menu"><span></span><span></span><span></span></div>
<!-- hamburger-menu -->
</div>
<!-- menu-wrapper -->
<ul class="menu-list accordion">
<li id="nav1" class="toggle accordion-toggle">
<span class="icon-plus"></span>
<a class="menu-link" href="#">Menu1</a>
</li>
<!-- accordion-toggle -->
<ul class="menu-submenu accordion-content">
<li><a class="head" href="#">Submenu1</a></li>
<li><a class="head" href="#">Submenu2</a></li>
<li><a class="head" href="#">Submenu3</a></li>
</ul>
<!-- menu-submenu accordon-content-->
<li id="nav2" class="toggle accordion-toggle">
<span class="icon-plus"></span>
<a class="menu-link" href="#">Menu2</a>
</li>
<!-- accordion-toggle -->
<ul class="menu-submenu accordion-content">
<li><a class="head" href="#">Submenu1</a></li>
<li><a class="head" href="#">Submenu2</a></li>
</ul>
<!-- menu-submenu accordon-content-->
<li id="nav3" class="toggle accordion-toggle">
<span class="icon-plus"></span>
<a class="menu-link" href="#">Menu3</a>
</li>
<!-- accordion-toggle -->
<ul class="menu-submenu accordion-content">
<li><a class="head" href="#">Submenu1</a></li>
<li><a class="head" href="#">Submenu2</a></li>
<li><a class="head" href="#">Submenu3</a></li>
<li><a class="head" href="#">Submenu4</a></li>
</ul>
<!-- menu-submenu accordon-content-->
</ul>
<!-- menu-list accordion-->
</div>
<!-- menu-container -->

jQuery - Toggle menu without using stopImmediatePropagation();

Currently the snippet only allows toggling of each menu when I un-comment the e.stopImmediatePropagation();.
The problem is I cannot use e.stopImmediatePropagation(); because I have to use an animation on the .button that would be killed by the stop.
How do I change the code to be able to toggle the menu's as is done when using e.stopImmediatePropagation();, but not have to use it.
To emulate problem: Click the Apple or Google logo (or Bell Icon) and then click it
again. The solution should remove .active from it's associated
.modal and it should close just like it does when clicking document (except for Bell Icon button which isn't set up to close when document is clicked). I just don't know how to acheive this without using e.stopImmediatePropagation();
$("[data-close]").click(function(e) {
const dataClose = $(this).attr("data-close");
const elem = $('[data-id="' + dataClose + '"]').length ?
$('[data-id="' + dataClose + '"]') :
$(dataClose);
if (elem.hasClass("active") && elem.is(":visible")) {
elem.removeClass("active");
/* e.stopImmediatePropagation();*/
}
});
$(".button").on("click", function() {
const id = $(this).prop("id");
$(".modal").each(function() {
$(this).toggleClass("active", $(this).data("id") == id);
});
});
$(document).on("click", function(e) {
if (
$(".apple-modal, .google-modal").hasClass("active") &&
!$(".modal, .modal *, .button").is(e.target)
) {
$(".modal").removeClass("active");
}
});
.buttons {
display: flex;
align-items: center;
}
.button {
height: 30px;
cursor: pointer;
border: 2px solid;
padding: 1rem;
font-size: 28px;
}
#icon {
color: silver;
}
.header {
height: 15px;
background: #eee;
}
.modal {
position: fixed;
top: 72px;
right: 15px;
z-index: 6;
opacity: 0;
visibility: hidden;
transform: scale(0.5);
transform-origin: top right;
transition: 0.15s;
box-shadow: 0 1.5px 4px rgba(0, 0, 0, 0.24), 0 1.5px 6px rgba(0, 0, 0, 0.12);
}
.modal:after {
content: "";
width: 15px;
height: 15px;
background: inherit;
position: absolute;
background: #eee;
top: -6px;
right: 8px;
opacity: 0;
visibility: hidden;
transform: rotate(45deg) scale(0.5);
transition: 0.15s;
}
.modal.active {
opacity: 1;
visibility: visible;
transform: scale(1);
}
.modal.active:after {
opacity: 1;
visibility: visible;
transform: rotate(45deg) scale(1);
}
<script src="https://pro.fontawesome.com/releases/v5.8.1/js/all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="buttons">
<img src="https://www.dignitasteam.com/wp-content/uploads/2015/09/3050613-inline-i-2-googles-new-logo-copy.png" class="button" id="google" data-close="google" />
<img src="https://www.arabianbusiness.com/sites/default/files/styles/full_img/public/images/2017/01/17/apple-logo-rainbow.jpg" class="button" id="apple" data-close="apple" />
<div class="button" id="icon" data-close="icon">
<i class="fas fa-bell"></i>
</div>
</div>
<div class="modal google-modal" data-id="google">
<div class="header">Google</div>
<ul>
<li>
First</li>
<li>
Second</li>
<li>
Third</li>
</ul>
</div>
<div class="modal apple-modal" data-id="apple">
<div class="header">Apple</div>
<ul>
<li>
First</li>
<li>
Second</li>
<li>
Third</li>
</ul>
</div>
<div class="modal icon-modal" data-id="icon">
<div class="header">Icon</div>
<ul>
<li>
First</li>
<li>
Second</li>
<li>
Third</li>
</ul>
</div>
I was able to implement what you want by adding the close modal functionality inside the click button and check if the modal for the current element is visible or not:
$(".button").on("click", function () {
const dataClose = $(this).attr("data-close");
const elem = $('[data-id="' + dataClose + '"]').length
? $('[data-id="' + dataClose + '"]')
: $(dataClose);
if (elem.hasClass("active") && elem.is(":visible")) {
elem.removeClass("active");
} else {
const id = $(this).prop("id");
$(".modal").each(function () {
$(this).toggleClass("active", $(this).data("id") == id);
});
}
});
$(document).on("click", function (e) {
if (
$(".apple-modal, .google-modal").hasClass("active") &&
!$(".modal, .modal *, .button").is(e.target)
) {
$(".modal").removeClass("active");
}
});
.buttons {
display: flex;
align-items: center;
}
.button {
height: 30px;
cursor: pointer;
border: 2px solid;
padding: 1rem;
font-size: 28px;
}
#icon {
color: silver;
}
.header {
height: 15px;
background: #eee;
}
.modal {
position: fixed;
top: 72px;
right: 15px;
z-index: 6;
opacity: 0;
visibility: hidden;
transform: scale(0.5);
transform-origin: top right;
transition: 0.15s;
box-shadow: 0 1.5px 4px rgba(0, 0, 0, 0.24), 0 1.5px 6px rgba(0, 0, 0, 0.12);
}
.modal:after {
content: "";
width: 15px;
height: 15px;
background: inherit;
position: absolute;
background: #eee;
top: -6px;
right: 8px;
opacity: 0;
visibility: hidden;
transform: rotate(45deg) scale(0.5);
transition: 0.15s;
}
.modal.active {
opacity: 1;
visibility: visible;
transform: scale(1);
}
.modal.active:after {
opacity: 1;
visibility: visible;
transform: rotate(45deg) scale(1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="buttons">
<img src="https://www.dignitasteam.com/wp-content/uploads/2015/09/3050613-inline-i-2-googles-new-logo-copy.png" class="button" id="google" data-close="google" />
<img src="https://www.arabianbusiness.com/sites/default/files/styles/full_img/public/images/2017/01/17/apple-logo-rainbow.jpg" class="button" id="apple" data-close="apple" />
<div class="button" id="icon" data-close="icon">
<i class="fas fa-bell"></i>
</div>
</div>
<div class="modal google-modal" data-id="google">
<div class="header">Google</div>
<ul>
<li>
First
</li>
<li>
Second
</li>
<li>
Third
</li>
</ul>
</div>
<div class="modal apple-modal" data-id="apple">
<div class="header">Apple</div>
<ul>
<li>
First
</li>
<li>
Second
</li>
<li>
Third
</li>
</ul>
</div>
<div class="modal icon-modal" data-id="icon">
<div class="header">Icon</div>
<ul>
<li>
First
</li>
<li>
Second
</li>
<li>
Third
</li>
</ul>
</div>

Trying to toggle class on group of items for accordion style functionality but it's acting funny

I am trying to toggle a class on the wrapper of a header (that you click to drop the body) and the body. The class changes the visibility, opacity, and max-height of the body to create the drop down effect.
This first item is dropped down by default. When another is open, all currently open items should close.
instead, when I click on a closed one it opens all of them but and closes the first one that is open by default.
here is my code:
$(".template_wrap").first().addClass("open");
$('.templates').find('.template_header').click(function(){
$(this).drop();
$('.template_header').not($(this)).drop();
});
$.fn.drop = function() {
$(this).parent(".template_wrap").toggleClass('open');
};
.page_center {
margin: 0 auto;
float: none;
}
.page_center.large {
width: 95%;
}
.page_center.medium {
width: 85%;
max-width: 1350px;
}
.page_center.small {
width: 85%;
max-width: 1130px;
}
.page_center.x-small {
width: 75%;
max-width: 680px;
}
.page_center:after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
* html .page_center { zoom: 1; } /* IE6 */
*:first-child+html .page_center { zoom: 1; } /* IE7 */
.template_wrap {
border: 1px solid #a32021;
width: 100%;
margin-bottom: 30px;
}
.template_header {
background: #a32021;
position: relative;
cursor: pointer;
padding: 1px 0 1px 2%;
}
.template_header:after {
position: absolute;
right: 2%;
top: 50%;
transform: translateY(-50%);
color: #fff;
font-size: 36px;
font-family:"FontAwesome";
content: "\f107";
transition: all 0.4s ease;
}
.template_wrap.open .template_header:after {
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
transition: all 0.4s ease;
content: "\f106";
top: 30%;
}
.template_header h2 {
color: #fff;
margin: 0;
line-height: 65px;
font-weight: 400;
}
.template_body {
visibility: hidden;
opacity: 0;
max-height: 0;
transition: opacity .4s ease-out, visibility .4s, max-height: .8s;
}
.template_wrap.open .template_body {
visibility: visible;
opacity: 1;
max-height: 10000px;
transition: opacity .4s ease-out, visibility .4s, max-height: .8s;
padding: 2%;
}
.template_links {
width: 50%;
float: left;
}
.template_links_wrap {
border: 1px solid #f47628;
padding: 0;
margin: 0;
list-style: none;
}
.template_links_wrap li {
padding-left: 3%;
line-height: 52px;
}
.template_links_wrap li:nth-child(odd) {
background: #fbe4d6;
}
.template_links_wrap li a {
color: #f47628;
}
.template_img {
width: 50%;
float: right;
}
.template_img img {
margin: 0 auto;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="content templates">
<div class="page_center medium">
<div class="template_wrap">
<div class="template_header">
<h2>Template Header</h2>
</div>
<div class="template_body">
<div class="page_center">
<div class="template_links">
<ul class="template_links_wrap">
<li>Download PDF</li>
<li>Download PDF</li>
<li>Download PDF</li>
</ul>
</div>
<div class="template_img">
<img src="images/template_placeholder.jpg">
</div>
</div>
</div>
</div>
<div class="template_wrap">
<div class="template_header">
<h2>Template Header</h2>
</div>
<div class="template_body">
<div class="page_center">
<div class="template_links">
<ul class="template_links_wrap">
<li>Download PDF</li>
<li>Download PDF</li>
<li>Download PDF</li>
</ul>
</div>
<div class="template_img">
<img src="images/template_placeholder.jpg">
</div>
</div>
</div>
</div>
<div class="template_wrap">
<div class="template_header">
<h2>Template Header</h2>
</div>
<div class="template_body">
<div class="page_center">
<div class="template_links">
<ul class="template_links_wrap">
<li>Download PDF</li>
<li>Download PDF</li>
<li>Download PDF</li>
</ul>
</div>
<div class="template_img">
<img src="images/template_placeholder.jpg">
</div>
</div>
</div>
</div>
</div>
</section>
Also, Something strange happens to the h2s where they move around based on various clicks. Any help would be appreciated.
This should do the trick:
$(".template_wrap").first().addClass("open");
$('.template_header').click(function(){
$('.template_wrap').removeClass("open");
$(this).parent().addClass("open");
})
Fiddle: https://jsfiddle.net/26kasg4t/
The trick here is to make all accordions close and then afterwards make this the only one open:
$('.template_wrap:first').addClass('open');
$('.template_header').click(function() {
if ($(this).parent().hasClass('open')) {
$('.template_wrap').removeClass('open');
$('.template_body').slideUp();
} else {
$('.template_wrap').removeClass('open');
$('.template_body').slideUp();
$(this).next('.template_body').slideDown();
$(this).parent().addClass('open');
}
});
Added a condition, should an accordion be open while it's clicked, it will just close.
SNIPPET
$('.template_wrap:first').addClass('open');
$('.template_header').click(function() {
if ($(this).parent().hasClass('open')) {
$('.template_wrap').removeClass('open');
$('.template_body').slideUp();
} else {
$('.template_wrap').removeClass('open');
$('.template_body').slideUp();
$(this).next('.template_body').slideDown();
$(this).parent().addClass('open');
}
});
.page_center {
margin: 0 auto;
float: none;
}
.page_center.large {
width: 95%;
}
.page_center.medium {
width: 85%;
max-width: 1350px;
}
.page_center.small {
width: 85%;
max-width: 1130px;
}
.page_center.x-small {
width: 75%;
max-width: 680px;
}
.page_center:after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
* html .page_center {
zoom: 1;
}
/* IE6 */
*:first-child+html .page_center {
zoom: 1;
}
/* IE7 */
.template_wrap {
border: 1px solid #a32021;
width: 100%;
margin-bottom: 30px;
}
.template_header {
background: #a32021;
position: relative;
cursor: pointer;
padding: 1px 0 1px 2%;
}
.template_header:after {
position: absolute;
right: 2%;
top: 50%;
transform: translateY(-50%);
color: #fff;
font-size: 36px;
font-family: "FontAwesome";
content: "\f107";
transition: all 0.4s ease;
}
.template_wrap.open .template_header:after {
-ms-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
transition: all 0.4s ease;
content: "\f106";
top: 30%;
}
.template_header h2 {
color: #fff;
margin: 0;
line-height: 65px;
font-weight: 400;
}
.template_body {
visibility: hidden;
opacity: 0;
max-height: 0;
transition: opacity .4s ease-out, visibility .4s, max-height: .8s;
}
.template_wrap.open .template_body {
visibility: visible;
opacity: 1;
max-height: 10000px;
transition: opacity .4s ease-out, visibility .4s, max-height: .8s;
padding: 2%;
}
.template_links {
width: 50%;
float: left;
}
.template_links_wrap {
border: 1px solid #f47628;
padding: 0;
margin: 0;
list-style: none;
}
.template_links_wrap li {
padding-left: 3%;
line-height: 52px;
}
.template_links_wrap li:nth-child(odd) {
background: #fbe4d6;
}
.template_links_wrap li a {
color: #f47628;
}
.template_img {
width: 50%;
float: right;
}
.template_img img {
margin: 0 auto;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="content templates">
<div class="page_center medium">
<div class="template_wrap">
<div class="template_header">
<h2>Template Header</h2>
</div>
<div class="template_body">
<div class="page_center">
<div class="template_links">
<ul class="template_links_wrap">
<li>Download PDF
</li>
<li>Download PDF
</li>
<li>Download PDF
</li>
</ul>
</div>
<div class="template_img">
<img src="images/template_placeholder.jpg">
</div>
</div>
</div>
</div>
<div class="template_wrap">
<div class="template_header">
<h2>Template Header</h2>
</div>
<div class="template_body">
<div class="page_center">
<div class="template_links">
<ul class="template_links_wrap">
<li>Download PDF
</li>
<li>Download PDF
</li>
<li>Download PDF
</li>
</ul>
</div>
<div class="template_img">
<img src="images/template_placeholder.jpg">
</div>
</div>
</div>
</div>
<div class="template_wrap">
<div class="template_header">
<h2>Template Header</h2>
</div>
<div class="template_body">
<div class="page_center">
<div class="template_links">
<ul class="template_links_wrap">
<li>Download PDF
</li>
<li>Download PDF
</li>
<li>Download PDF
</li>
</ul>
</div>
<div class="template_img">
<img src="images/template_placeholder.jpg">
</div>
</div>
</div>
</div>
</div>
</section>

Categories

Resources