click outside burger menu to close using javascript - 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>

Related

How to set relative position of tooltip in CSS/JS?

I know there are lots of similar questions but I can't get it to work and hope you can help me.
I have a nested list of items. Mostly simple hrefs but some are links which should call a copy-to-clipboard function and display a success message in as span afterwards.
The message should be displayed above the link and centered. On a desktop with high resolution there is no problem. On mobile,unfortunately showing the span uses space and moves the hrefs + the position is anywhere but above and in the middle.
Using data-tooltip class templates didn't work for me because they normally use "hover". In my case the span should only be displayed after clicking the link and shouldn't mess up the other elements.
function CopyToClipboard(id) {
// do copy stuff here
// [...]
// showing tooltip
var span_element = document.getElementById(id).parentElement.querySelector('span');
if(span_element != null) {
span_element.style.display = "inline";
setTimeout( function() {
span_element.style.display = "none";
}, 2000);
}
}
body {
margin-left: 0px;
}
ul {
padding-left: 20px;
}
div.container {
margin: 10px;
width: 98%;
word-break: break-all;
}
.custom-tooltip {
padding: 4px;
background-color: grey;
color: #fff;
position: relative;
bottom: 2em;
right: 5em;
display: none;
}
<html lang="de" class=" heujtnrdy idc0_345">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.90">
<link rel="stylesheet" href="index_tmp.css">
<script type="text/javascript" src="index_tmp.js"></script>
</head>
<body>
<div class="container">
<ul>
<li>
<span>Layer 1</span>
<ul>
<li>
<span>Layer 2</span>
<ul>
<li>
<span>Layer 3</span>
<ul>
<li>
<div>
<table>
<tr>
<td><a id="uGzkLTVmLY" onclick="CopyToClipboard('uGzkLTVmLY');return false;" href="#">Short text to copy</a><span class="custom-tooltip">Copied!</span></td>
</tr>
</table>
</div>
</li>
<li>
<div>
<table>
<tr>
<td><a id="VF5DVP6tVv" onclick="CopyToClipboard('VF5DVP6tVv');return false;" href="#">Looooooooooooooooooong text to copy</a><span class="custom-tooltip">Copied!</span></td>
</tr>
</table>
</div>
</li>
<li>
<div>
<table>
<tr>
<td><a id="VF5DVP6tVv" onclick="CopyToClipboard('VF5DVP6tVv');return false;" href="#">Even loooooooooooooooooooooooooooooooooooooooooooooooooooooonger text to copy</a><span class="custom-tooltip">Copied!</span></td>
</tr>
</table>
</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</body>
</html>
-- Update 05.02.2023 --
Here my modified CSS, based on granite's alternative solution. This looks like this:
.modal {
display: none;
position: fixed;
padding-top: 50%;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.4);
text-align: center;
justify-content: center;
}
.modal-content {
background-color: grey;
border: 0.5px solid grey;
border-radius: 3px;
color: #fff;
text-align: center;
margin: 0 auto;
padding: 2px;
padding-left: 10px;
padding-right: 10px;
font-size: 1.0em;
font-family: monospace;
font-weight: 700;
bottom: 1em !important;
position: fixed;
}
As a secondary option (via modal):
Html: 2 lines code.
CSS: 7 extra lines code.
JS: 10 extra lines code.
Just need to get the JS CopyToClipboard to link up.
<button id="MBtn" id="VF5DVP6tVv" onclick="CopyToClipboard('VF5DVP6tVv');return false;">long text to copy</button>
<div id="Modal" class="modal"><div class="modal-content">Copied!</div></div>
.modal {
display: none;
position: fixed;
padding-top: 25%;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.4);
}
.modal-content {
background-color: #eff;
text-align:center;
margin: 0 auto;
padding: 3px;
width:4em;
}
var modal = document.getElementById("Modal");
var btn = document.getElementById("MBtn");
btn.onclick = function() {
modal.style.display = "block";
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}

Fire only when clicking on parent element 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>

How can I get an animated Dropdown-Menu?

I wanna have an animated Dropdown-menu as a Navigation!
In Css I've set transition height to 1s and in Javascript I add a value
of for the height property in an Eventlistener. When the ham-symbol is
clicked the menu should go down in a transition of 1s. The problem is that when I click the ham-symbol it does't move with transition...it just appears... I recently found out when I add display: block in the css dropdown menu it works, but then obviously the toggle click ham-symbol doesnt work anymore! Please help!
<nav>
<a href="#">
<img id="ham" alt="toggle menu" src="Images/hamburger.svg">
</a>
<div id="dropdown" class="hide-mobile">
<ul>
<li>
Home
</li>
<li>
Service
</li>
<li>
Einbruchschutz
</li>
</ul>
</div>
</nav>
#dropdown {
/* display: block */
border-top: 3px solid red;
position: absolute;
width: 80%;
top: 100%;
left: 10%;
height: 0;
background: #fff;
padding-top: 2.2rem;
box-shadow: 0 2px 2px lightgrey;
z-index: 1;
transition: height 1s;
}
let menu = document.getElementById('ham');
let nav = document.getElementById('dropdown');
menu.addEventListener('click', function(e) {
nav.classList.toggle('hide-mobile');
nav.style.height = "400px";
})
Take a look at this codepen.
You can make it better but your basic requirement is met.
You just needed to:
toggle the height, not the top.
set overflow-y: hidden;
If you want to keep your solution you can try something like that :
let menu = document.getElementById('ham');
let nav = document.getElementById('dropdown');
var isOpen = false;
menu.addEventListener('click', function(e) {
if (isOpen == false){
nav.classList.toggle('hide-mobile');
nav.style.top = "-100%";
isOpen = true;
}
else{
nav.classList.toggle('hide-mobile');
nav.style.top = "0%";
isOpen = false;
}
})
#dropdown {
border-top: 3px solid red;
position: absolute;
width: 80%;
top: 0;
left: 10%;
background: #fff;
padding-top: 2.2rem;
box-shadow: 0 2px 2px lightgrey;
z-index: 1;
transition: 1s;
}
/* Just for the example */
img{
height: 50px;
width: 50px;
margin-left:-5px;
margin-top:-5px;
}
<nav>
<a href="#">
<img id="ham" alt="toggle menu" src="https://static.thenounproject.com/png/195031-200.png">
</a>
<div id="dropdown" class="hide-mobile">
<ul>
<li>
Home
</li>
<li>
Service
</li>
<li>
Einbruchschutz
</li>
</ul>
</div>
</nav>
Click on "Run code snippet" to see the animation. If that does not work there is definitely a problem with your browser display, try on another machine and check that javascript is not disabled.
JSFiddle :
https://jsfiddle.net/t3wrhjpq/2/

setting position to absolute and top to 0 in css causing javascript classList.toggle() to not work

I'm using the following javascript function to toggle a nav menu:
var navList = document.getElementById("navbar-list-landing");
var openBtn = document.getElementById("nav-open-landing");
function toggleNav() {
navList.classList.toggle("open");
}
It works fine until I add the following CSS to the id of the ul I'm trying to hide:
position: absolute;
top: 0;
The javascript function then will not run at all (using a console.log at the beginning of the function).
I'm including a code snippet of the entire nav below (stripped of all but the necessary CSS so it's a little ugly).
var navList = document.getElementById("navbar-list-landing");
var openBtn = document.getElementById("nav-open-landing");
function toggleNav() {
console.log("test");
navList.classList.toggle("open");
}
#nav-landing {
position: fixed;
background: #fff;
height: 82px;
width: 100%;
}
#nav-landing #nav-logo-landing {
display: block;
float: left;
width: 220px;
}
#nav-landing #navbar-list-landing {
position: absolute;
top: 0;
height: 100vh;
width: 100vw;
opacity: 0;
margin: 0;
}
#nav-landing #dropdown-more {
display: none;
}
#nav-landing #nav-open {
display: inline-block;
background: #fff;
width: 20%;
height: 100%;
border: 1px solid black;
}
#nav-landing .open {
opacity: 1 !important;
}
<nav class="nav clearfix" id="nav-landing">
<img src="./img/lenus-logo.png" alt="Lenus Logo" id="nav-logo-landing" />
=
<ul class="navbar-list" id="navbar-list-landing">
<li class="navbar-item">Home</li>
<li class="navbar-item">About Us</li>
<li class="navbar-item">Services</li>
<li class="navbar-item">Macra</li>
<li class="navbar-item">Schedule a Consult</li>
<li class="navbar-item">More</li>
</ul>
<div class="dropdown" id="dropdown-more">
<ul class="navbar-sublist" id="#sublist-more">
<li class="navbar-subitem">Careers</li>
<li class="navbar-subitem">Contact</li>
</ul>
</div>
</nav>
Thanks in advance.

Material Components: Keeping Menu "Open" when clicking inside

MATERIAL COMPONENTS FOR THE WEB (MENUS)
This question is in relation to the Menu Component:
I've modified the code so that the menu opens when hovered instead of clicked. I'm now trying to make the menu stay open or closed when certain elements inside the menu are clicked on..But I'm having trouble getting it to work.
Can anyone help?
Codepen Link:
https://codepen.io/oneezy/pen/prejpw
Example:
When <li class="wont-close"> is clicked, the menu won't close. menu.show();
When <li class="will-close"> is clicked, the menu will close. menu.hide();
Here's my attempts:
HTML
<section class="demo">
<div class="mdc-tab-bar">
<!-- Hover Toggle (Wrapper) -->
<div class="mdc-tab-wrapper hover-toggle">
<!-- Button (For Looks) -->
<a class="mdc-button mdc-button--raised mdc-button--primary mdc-tab mdc-ripple-upgraded" role="tab">
Hover Menu
</a>
<!-- Hover Menu (Toggles Show/Hide)-->
<nav class="mdc-simple-menu mdc-tab-items-wrapper" tabindex="-1">
<ul class="mdc-simple-menu__items mdc-list" role="menu" aria-hidden="true">
<!-- Won't Close (When Clicked) -->
<li class="mdc-list-item wont-close clone-me" role="menuitem" tabindex="0">
<a class="category-items flex-horizontal between-stretch" href="#">
<i class="material-icons margin-r-5">keyboard_arrow_right</i>
<span>Won't Close</span>
</a>
</li>
<!-- Will Close (When Clicked) -->
<li class="mdc-list-item will-close" role="menuitem" tabindex="0">
<a class="category-items flex-horizontal between-stretch" href="#">
<i class="material-icons margin-r-5">close</i>
<span>Will Close</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
JS
/* Hover Tabs
*********************************/
function hoverTabs() {
var menuEls = document.querySelectorAll('.mdc-simple-menu');
menuEls.forEach((el, i) => {
var menu = new mdc.menu.MDCSimpleMenu(el);
var toggle = $(el).closest('.hover-toggle')[0];
var wontClose = $(el).closest('.wont-close'); // Not working...
var willClose = $(el).closest('.will-close'); // Not working...
toggle.addEventListener('mouseover', function() {
menu.show();
});
toggle.addEventListener('mouseleave', function() {
menu.hide();
});
/* Attempt #1 (Not working...)
*******************************************************/
// wontClose.addEventListener('click', function() {
// menu.show();
// });
// willClose.addEventListener('click', function() {
// menu.hide();
// });
/* Attempt #2 (Not working...)
*******************************************************/
// $('.wont-close').on('click', function(e) {
// e.preventDefault();
// menu.show();
// });
//
// $('.will-close').on('click', function(e) {
// e.preventDefault();
// menu.hide();
// });
});
}
$(document).ready(function() {
hoverTabs();
});
When in doubt, create a pure CSS solution...
I'm not accepting my answer as THE ANSWER because this is a hack.
I just want to include this here to show my quick fix that does the exact same thing (right on down to the cubic-bezier animation).
NOTE: I'm still using the Material Design Styles it ships with... Just not any of the JS.
Codepen: https://codepen.io/oneezy/pen/PKpJXV
HTML
<!-- Hover Toggle (Wrapper) -->
<div class="mdc-tab-wrapper hover-toggle clone-menu">
<!-- Button (For Looks) -->
<a class="mdc-button mdc-button--raised mdc-button--primary">Hover Menu</a>
<!-- Hover Menu (Toggles Show/Hide)-->
<nav class="mdc-simple-menu mdc-simple-menu--open" tabindex="-1">
<ul class="mdc-simple-menu__items mdc-list" role="menu" aria-hidden="true">
<!-- Won't Close (When Clicked) -->
<li class="mdc-list-item clone-me" role="menuitem" tabindex="0">
<a class="category-items flex-horizontal between-stretch" href="#">
<i class="material-icons margin-r-5">keyboard_arrow_right</i>
<span>Menu Item</span>
</a>
</li>
</ul>
</nav>
</div>
CSS
/* Reset
========================================================================= */
* { box-sizing: border-box; margin: 0; padding: 0; text-decoration: none; }
html,
body,
main { display: flex; flex-direction: column; height: 100%; }
section { padding: 5%; }
a { color: var(--mdc-theme-primary); }
h1 { background: black; color: white; padding: .25rem 1rem; position: relative; }
h1 span { font-weight: normal; font-size: 16px; position: absolute; right: 24px; top: 14px; display: inline-block; text-transform: uppercase; }
/* Material Design Menu
========================================================================= */
/* Menu Styles */
.wrapper { position: relative; display: flex; justify-content: space-between; }
.wrapper .hover-toggle { display: inline-block; position: relative; }
.wrapper .hover-toggle .mdc-button { z-index: 2; position: relative; color: white; min-width: auto; }
.wrapper .hover-toggle .mdc-simple-menu { width: 100%; top: 100% !important; position: absolute; right: 0 !important; left: 0 !important; z-index: 1; padding: 0; }
.mdc-simple-menu .mdc-list,
.mdc-simple-menu .mdc-list-group { padding: 0; }
/* Hover Effects */
.hover-toggle .mdc-simple-menu--open { opacity: 0; transform: scale(0, 0) translateY(-40px); transition: .2s cubic-bezier(0, 0, 0.2, 1); position: absolute; transform-origin: left top 0px; left: 0px; top: 0px; }
.hover-toggle:hover .mdc-simple-menu--open { opacity: 1; transform: scale(1,1) translateY(0); }
.mdc-simple-menu .mdc-list-item:before { opacity: 0; position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-transition: opacity .12s cubic-bezier(0,0,.2,1); transition: opacity .12s cubic-bezier(0,0,.2,1); border-radius: inherit; background: var(--mdc-theme-primary); content: ""; }
.mdc-simple-menu .mdc-list-item:hover:before { opacity: .1; }
.mdc-simple-menu .mdc-list-item:active:before { opacity: .2; }

Categories

Resources