I am making a menu with pure Vanilla JS, because I want it to implement it in an Angular 8 project.
It is working good at some point, because it opens the hidden menu very good. The thing is that when I want to open a second level hidden menu , then it closes everything. For example if you click in 'Soluciones' link, then it opens the submenu very good. After that you must be able to click 'Correo y herramientas' in order to show a second level hidden menu, which is: Correo 1, Correo 2, Correo 3 links; but before showing this last links, it closes everything.
I have a codepen link to show this: https://codepen.io/Bungo808/pen/ZEBpmXG
Any advice would be helpfull!!
My HTML
<div class="red">
<nav id="nav" class="sub-menu open">
<ul class="list-unstyled">
<li id="subb">
<a class="link">Quiénes somos</a>
<img id="iplus" class="splus" src="../../assets/img/splus.svg" alt="">
<ul id="smenu" >
<li>
<a class="link">Sobre eSource</a>
</li>
<li>
<a class="link">Amarello</a>
</li>
</ul>
</li>
<li id="subb">
<a class="link">Soluciones</a>
<img id="iplus" class="splus" src="../../assets/img/splus.svg" alt="">
<ul id="smenu" >
<li id="subb">
<a class="link">Correo y herramientas</a>
<ul>
<li><a class="link">Correo 1</a></li>
<li><a class="link">Correo 2</a></li>
<li><a class="link">Correo 3</a></li>
</ul>
</li>
<li id="subb">
<a class="link">Infrastructure as a Service</a>
<ul>
<li><a class="link">Infra 1</a></li>
<li><a class="link">Infra 2</a></li>
<li><a class="link">Infra 3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
<div class="overlay"></div>
</div>
My JS
let list_items = document.querySelectorAll('#subb');
// Show Submenu
for (let i = 0; i < list_items.length; i++) {
list_items[i].addEventListener("click", show);
}
function show() {
this.classList.toggle("myClass");
console.log('I clicked it!')
}
A part of my CSS, which is the responsible to open the hidden menu
.sub-menu {
padding: 0 0 0 2%;
left: 0px;
top: 0;
transition: all 0.3s ease;
height: 100%;
width: 280px;
position: fixed;
margin: 0;
background-color: #f9f9f9;
border-radius: 0;
z-index: 10;
overflow: hidden;
}
.sub-menu > ul {
width: 100%;
height: 100%;
margin-top: 60px;
}
.sub-menu li {
position: relative;
display: block;
list-style: none;
padding: 2px 0 2px 14px;
margin-left: 0;
cursor: pointer;
color: white;
transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
&:first-child{
// border: 1px solid red;
}
}
.sub-menu li a {
color: #40465f;
font-size: 16px;
font-weight: 300;
width: 100%;
display: block;
line-height: 22px;
padding: 6px 0;
&:hover{
color: #2487FC;
text-decoration: none;
}
}
.sub-menu ul ul li a {
color: #40465f;
font-size: 14px;
font-weight: 300;
width: 100%;
line-height: 22px;
padding: 6px 0;
&:hover{
color: #2487FC;
text-decoration: none;
}
}
.sub-menu ul ul ul li a {
color: #40465f;
font-size: 14px;
font-weight: 300;
width: 100%;
display: block;
line-height: 22px;
padding: 6px 0;
&:hover{
color: #2487FC;
text-decoration: none;
}
}
.sub-menu ul ul{
display: none;
background: white;
}
#subb.myClass > ul{
display: block;
}
.sub-menu ul ul ul{
display: none;
border: 1px solid red;
}
The click event is propagating over and over again. So eventually the class gets toggled off. To prevent this add .stopPropagation(); to your show() function like this:
function show(e) {
e.stopPropagation();
this.classList.toggle("myClass");
console.log('I clicked it!')
}
Related
I have 2 versions of a website i made one in english one in french. The navbar for the english version works perfectly on my computer and live on the internet so When i test the french website version on my computer the navbar works exactly as it should yet when live on the internet it's stuck at the top of the page, where as its suppose to be about 5 cms under the top. Here is the html and css code:
<div id="headerNav" class="navbar-collapse collapse float--right">
<!-- Header Nav Links Start -->
<ul class="header--nav-links nav">
<li class="dropdown">
<li>Hébergement Web</li>
<li class="dropdown">
Forfaits
<ul class="dropdown-menu">
<li>Hébergement Partagé</li>
<li>Hébergement WordPress</li>
<li>Hébergement Cloud VPS</li>
</ul>
</li>
<li>Noms de domaines</li>
<li>Emails</li>
<li>E-commerce</li>
<li class="dropdown">
Services
<ul class="dropdown-menu">
<a href="à propos de.html" class="dropdown-toggle" data-
toggle="dropdown">à propos de</a>
<li>Services</li>
<li>UTD Webhosting</li>
<li>Nos Datacenters</li>
</li>
<ul class="dropdown-menu">
<li>Coming Soon</li>
<li>404</li>
</ul>
</li>
</ul>
<li>Contact</li>
</ul>
<!-- Header Nav Links End -->
</div>
</div>
</nav>
<!-- Header Navbar End -->
</header>
CSS:
.header--navbar > .container {
position: relative;
}
.header--navbar .navbar-header {
float: none;
}
.header--cart-btn {
float: none;
position: absolute;
top: 1px;
right: 85px;
margin-left: 0;
}
.header--navbar .navbar-toggle {
display: block;
}
.header--navbar .navbar-collapse {
float: none;
display: none !important;
position: absolute;
left: 15px;
right: 15px;
max-height: -340px;
box-shadow: 0 3px 8px rgba(0, 0, 0, .085);
overflow: auto !important;
}
.header--navbar .navbar-collapse.collapsing,
.header--navbar .navbar-collapse.in {
display: block !important;
}
.header--nav-links {
margin-top: 12px;
margin-left: 0;
margin-right: 0;
color: #222;
background-color: #fff;
}
.header--nav-links > li {
float: none;
}
.header--nav-links > li > a {
display: block;
padding-left: 20px;
padding-right: 20px;
}
.header--nav-links > .dropdown > .dropdown-menu {
float: none;
position: relative;
margin-top: 0;
padding: 0;
box-shadow: none;
}
.header--nav-links > .dropdown > .dropdown-menu a {
padding-left: 30px;
padding-right: 30px;
}
.dropdown-menu .dropdown-menu {
float: none;
position: relative;
top: 0;
left: 0;
margin-left: 0;
padding: 0;
box-shadow: none;
}
.dropdown-menu .dropdown-toggle:before {
content: "\f107";
}
.header--nav-links > .dropdown > .dropdown-menu .dropdown-menu > li > a {
padding-left: 40px;
padding-right: 40px;
}
Quite a few of your tags (ul, li, also div) aren't closed properly in the code you posted. Browsers will try to interpret this in some way, but not necessarily the way you intended it, so this might be a cause for your problem.
I fixed those unclosed tags in the snippet below. It's hard to check your CSS, since most of the CSS rules you posted don't apply at all in the snippet, since they use the class .header--nav-links and similar in their selectors which isn't included in your HTML code.
Nevertheless, maybe the edited HTML code already fixes the display problem you are mentioning.
.header--navbar>.container {
position: relative;
}
.header--navbar .navbar-header {
float: none;
}
.header--cart-btn {
float: none;
position: absolute;
top: 1px;
right: 85px;
margin-left: 0;
}
.header--navbar .navbar-toggle {
display: block;
}
.header--navbar .navbar-collapse {
float: none;
display: none !important;
position: absolute;
left: 15px;
right: 15px;
max-height: -340px;
box-shadow: 0 3px 8px rgba(0, 0, 0, .085);
overflow: auto !important;
}
.header--navbar .navbar-collapse.collapsing,
.header--navbar .navbar-collapse.in {
display: block !important;
}
.header--nav-links {
margin-top: 12px;
margin-left: 0;
margin-right: 0;
color: #222;
background-color: #fff;
}
.header--nav-links>li {
float: none;
}
.header--nav-links>li>a {
display: block;
padding-left: 20px;
padding-right: 20px;
}
.header--nav-links>.dropdown>.dropdown-menu {
float: none;
position: relative;
margin-top: 0;
padding: 0;
box-shadow: none;
}
.header--nav-links>.dropdown>.dropdown-menu a {
padding-left: 30px;
padding-right: 30px;
}
.dropdown-menu .dropdown-menu {
float: none;
position: relative;
top: 0;
left: 0;
margin-left: 0;
padding: 0;
box-shadow: none;
}
.dropdown-menu .dropdown-toggle:before {
content: "\f107";
}
.header--nav-links>.dropdown>.dropdown-menu .dropdown-menu>li>a {
padding-left: 40px;
padding-right: 40px;
}
<div id="headerNav" class="navbar-collapse collapse float--right">
<!-- Header Nav Links Start -->
<ul class="header--nav-links nav">
<li class="dropdown">Hébergement Web</li>
<li class="dropdown">
Forfaits
<ul class="dropdown-menu">
<li>Hébergement Partagé</li>
<li>Hébergement WordPress</li>
<li>Hébergement Cloud VPS</li>
</ul>
</li>
<li>Noms de domaines</li>
<li>Emails</li>
<li>E-commerce</li>
<li class="dropdown">
Services
<ul class="dropdown-menu">
à propos de
<li>Services</li>
<li>UTD Webhosting</li>
<li>Nos Datacenters</li>
</ul>
<ul class="dropdown-menu">
<li>Coming Soon</li>
<li>404</li>
</ul>
</li>
<li>Contact</li>
</ul>
<!-- Header Nav Links End -->
</div>
<!-- Header Navbar End -->
I'm using a list as a navigation and CSS to design a horizontal nav for the main pages/ vertical nav for the subpages of "Diet".
I apply JavaScript to hide/ show the subpage links in the navigation. It works, but when the page is loaded the 3 links are shown - after I hovered over the item "Diet" they are hidden. If I hover again, then it is shown again and works as it should.
Basically, how can I make sure that the three links are hidden from the beginning?
Thank you in advance!
$(document).ready(function() {
$("nav li:has(ul)").hover(function() {
$(this).find("ul").slideDown();
}, function() {
$(this).find("ul").hide();
});
});
.navUnordList {
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
}
.navListElmnt {
float: left;
position: right;
font-family: Verdana, sans-serif;
font-size: 75%;
}
.navListElmntVert {
list-style: none;
text-align: left;
font-size: 0.8em;
margin: 0;
margin-bottom: 0.1em;
margin-top: 0.1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<nav>
<ul class="navUnordList">
<li class="navListElmnt">Example</li>
<li class="navListElmnt">Diet
<ul class="navUnordList">
<li class="navListElmntVert"><a href="page3-1.html">Food and Drink </li>
<li class="navListElmntVert"><a href="page3-2.html">Balanced Diet</li>
<li class="navListElmntVert"><a href="page3-3.html">Nutrition</li>
</ul>
</li>
</ul>
</nav>
Just add a display: none to the submenu:
.navListElmnt > .navUnordList {
display:none;
}
If I can express a personal note, these class names are bad, difficult to remember and to write.
$(document).ready(
function()
{
$("nav li:has(ul)").hover(
function()
{
$(this).find("ul").slideDown();
}
,
function()
{
$(this).find("ul").hide();
});
}
);
.navUnordList{
list-style:none;
margin:0;
padding:0;
overflow:hidden;
}
.navListElmnt{
float:left;
position:right;
font-family: Verdana, sans-serif;
font-size: 75%;
}
.navListElmntVert{
list-style: none;
text-align: left;
font-size: 0.8em;
margin: 0;
margin-bottom: 0.1em;
margin-top:0.1em;
}
.navListElmnt > .navUnordList {
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<nav>
<ul class="navUnordList">
<li class="navListElmnt">Example</li>
<li class="navListElmnt">Diet
<ul class="navUnordList">
<li class="navListElmntVert"><a href="page3-1.html">Food and Drink </li>
<li class="navListElmntVert"><a href="page3-2.html">Balanced Diet</li>
<li class="navListElmntVert"><a href="page3-3.html">Nutrition</li>
</ul>
</li>
</ul>
</nav>
To hide the options to start with you can set them as display: none in CSS.
Also note that the JS is redundant, as you can have the same logic in CSS, which is preferred as it's hardware accelerated. Try this:
.navUnordList {
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
}
.navUnordList li ul li {
display: none;
}
.navListElmnt {
float: left;
position: right;
font-family: Verdana, sans-serif;
font-size: 75%;
}
.navListElmnt:hover > ul > li {
display: block;
}
.navListElmntVert {
list-style: none;
text-align: left;
font-size: 0.8em;
margin: 0;
margin-bottom: 0.1em;
margin-top: 0.1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<nav>
<ul class="navUnordList">
<li class="navListElmnt">Example</li>
<li class="navListElmnt">
Diet
<ul class="navUnordList">
<li class="navListElmntVert">Food and Drink</li>
<li class="navListElmntVert">Balanced Diet</li>
<li class="navListElmntVert">Nutrition</li>
</ul>
</li>
</ul>
</nav>
You can actually have a CSS only solution for this. Keep height 0px by default and make it auto on hover like this:
.navUnordList {
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
}
.navListElmnt {
float: left;
position: right;
font-family: Verdana, sans-serif;
font-size: 75%;
}
.navListElmntVert {
list-style: none;
text-align: left;
font-size: 0.8em;
margin: 0;
margin-bottom: 0.1em;
margin-top: 0.1em;
}
.navListElmnt>.navUnordList {
height: 0px;
}
.navListElmnt:hover>.navUnordList {
height: auto;
}
<nav>
<ul class="navUnordList">
<li class="navListElmnt">Example</li>
<li class="navListElmnt">Diet
<ul class="navUnordList">
<li class="navListElmntVert">Food and Drink </li>
<li class="navListElmntVert">Balanced Diet</li>
<li class="navListElmntVert">Nutrition</li>
</ul>
</li>
</ul>
</nav>
Note: This does take away the slide down animation cos of height:auto
But you can have animated version too, if you are ready to measure how much height each submenu takes like this:
.navUnordList {
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
}
.navListElmnt {
float: left;
position: right;
font-family: Verdana, sans-serif;
font-size: 75%;
}
.navListElmntVert {
list-style: none;
text-align: left;
font-size: 0.8em;
margin: 0;
margin-bottom: 0.1em;
margin-top: 0.1em;
}
.navListElmnt>.navUnordList {
height: 0px;
transition: all 0.2s ease;
}
.navListElmnt:hover>.navUnordList {
height: 50px;
}
<nav>
<ul class="navUnordList">
<li class="navListElmnt">Example</li>
<li class="navListElmnt">Diet
<ul class="navUnordList">
<li class="navListElmntVert">Food and Drink </li>
<li class="navListElmntVert">Balanced Diet</li>
<li class="navListElmntVert">Nutrition</li>
</ul>
</li>
</ul>
</nav>
I'm currently working on a website. I wanted to make it easier to people with disabilities to use. My boss is blind but he uses the program "JAWS" to navigate through things on his computer. What I'm trying to do is when he does on this website, he can press "tab" and the "hover menu" pops open.
.menu .arrow {
font-size: 11px;
line-height: 0%;
}
.menu li:hover .sub-menu {
z-index: 1;
opacity: 1;
}
.sub-menu {
width: 160%;
padding: 5px 0px;
position: absolute;
top: 100%;
left: 0px;
z-index: -1;
opacity: 0;
transition: opacity linear 0.15s;
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.2);
background: #2e2728;
}
.sub-menu li {
display: block;
font-size: 16px;
}
.sub-menu li a {
color: white;
}
.menu > ul > li {
float: left;
display: inline-block;
position: relative;
font-size: 19px;
}
<link rel="stylesheet" href="http://s3.amazonaws.com/codecademy-content/courses/ltp/css/bootstrap.css">
<nav class="menu">
<ul class="nav nav-pills" class="clearfix">
<li class="active"><a>Home</a>
</li>
<li>About<span class="arrow">▼</span>
<ul class="sub-menu">
<li><a align="left" href="#">About the Center</a>
</li>
<li>Membership
</li>
<li>History
</li>
<li>Mission
</li>
<li>Event Calendar
</li>
<li> News
</li>
</ul>
</li>
</ul>
</nav>
And this is what I tried to do.
if (window.addEventListener) {
var keys = "16";
window.addEventListener("keydown", function(e) {
keys.push(e.keyCode);
if (keys.toString() >= 0) {
document.getElementById("about").hover();
};
});
};
I have an accordion on my website and I would like for the accordion to be open at the right level depending on where the active class is. I have made a JSFiddle.
JS:
$(document).ready(function ($) {
$('.servicesub').find('.servicesubitem').click(function () {
if ($(this).next().is(':visible')) {
//Collapse
$(this).next().slideToggle('fast');
$(this).removeClass('active');
// $("#footer-wrapper").animate({marginTop: "0px"}, 'fast');
} else {
//Expand
$(this).next().slideToggle('fast');
$(this).siblings().removeClass('active');
$(this).addClass('active');
//hide other panels
$(".servicesubli").not($(this).next()).slideUp('fast');
//$("#footer-wrapper").animate({marginTop: "200px"}, 'fast');
}
});
});
HTML:
<div class="col-xs-12 col-md-3 col-lg-3 servicesub" id="servicesub" >
<li class="servicesubitem active">
<span class="subitem">Web Design,
<br>
Multimedia & Email</span><span class="fa1 fa-globe"> </span>
</li>
<div class="servicesubli">
<ul>
<a href="domains.php">
<li>
Domain Registration
</li>
</a>
<a href="webdesign.php">
<li>
Web Design & Development
</li>
</a>
<a href="webhosting.php">
<li>
Web Hosting
</li>
</a>
<a href="email.php">
<li>
Managed Email Systems
</li>
</a>
</ul>
</div>
<li class="servicesubitem">
<span class="subitem">Vessel
<br>
Security</span><span class="fa1 fa-lock"> </span>
</li>
<div class="servicesubli">
<ul>
<a href="tracking.php">
<li>
Yacht Tracking
</li>
</a>
<a href="ssas.php">
<li>
SSAS
</li>
</a>
<a href="#">
<li>
SAT C
</li>
</a>
</ul>
</div>
</div>
CSS:
* Service Sub */
.servicesub { padding:10px; }
.servicesub ul { list-style-type: none; padding: 0px; color: #fff;}
.servicesub li{ font-size: 14px; height: 70px; padding: 17px 0px 10px 20px; margin-top: 10px; text-transform: uppercase; }
.servicesub li a {text-decoration: none;}
.servicesub li a:hover {color:#fff;}
.servicesub li { background-color: #017CEB; }
.servicesub li:hover { background-color: #015BAC; }
.servicesub li.active { background-color: #015BAC; }
.servicesub span:after { color:#fff; font-family: FontAwesome; display: inline-block; width: 1.2em; font-size: 40px; position: absolute; text-align: center; margin-top: -9px; }
#servicesub.stick { position: fixed; top: 80px; max-width: 293px; }
.subitem { color:#fff; height:58px; width: 215px; position: absolute; right: 10px; text-align: center; }
.servicesubitem { cursor: pointer; }
.servicesubli { cursor: pointer; display: none; }
.servicesubli.default { display: block; }
.servicesubli ul { width: 100%; font-size: 14px;}
.servicesubli li { padding: 8px; margin-top: 1px; text-transform: uppercase; height: 35px; text-align: center;}
.servicesubli a { text-decoration: none; color: #fff; }
.servicesub .getintouch { background-color: #00539f; padding: 10px; height: auto;}
.servicesub .getintouch:hover { background-color: #00539f; }
.servicesub .getintouch h3 { color: #fff; text-align: center; }
.servicesub .getintouch p { color:#fff; text-align: center; }
As you can see the accordion works to click on and the active class (which is set manually for this demo) is there I just want it so that the correct accordion part is toggled when the page is loaded. Thanks in advance.
To recycle your logic, You can just add your .active class to whichever element you wish, then search for .servicesubli.active on ready. Observe the following...
<div class="servicesubli active">
$(function() {
[...]
$('.servicesubli.active').slideToggle('fast');
});
JSFiddle Link - demo
Per comments, if you wish to target off servicesubitem.active, just modify to the following...
$('.servicesubitem.active').next('.servicesubli').addClass('active').slideToggle('fast');
JSFiddle Link - demo - .servicesubitem.active selector
Well you just need to trigger the click event once the page is loaded like below:
$('.servicesub').find('.active').trigger( "click" );
See the jsfiddle here: http://jsfiddle.net/beroza/a1mbgyqx/
html:
<div id="menu" class="menu">
<ul class="headlines">
<li id="item1" onclick="checklist(this)">
<button onclick="myFunction()">g</button>
</li>
<li id="item2">
<button onclick="myFunction2()">a </button>
</li>
<li id="item3">b </li>
<li id="item4">c </li>
<li id="item5">d </li>
<li id="item6">e </li>
<li id="item7">f </li>
</ul>
</div>
CSS:
lu, li {
list-style-type: none;
font-size: 1.5em;
height: 40px;
width: 150px;
text-align: right;
border-style: none;
}
.menu {
width: 150px;
height: 350px;
}
.menu li {
position: relative;
top: 150px;
bottom: 0;
left: 725px;
right: 0;
margin: auto;
border-style: none;
}
.permahover li {
opacity: 1;
left: 10%;
}
.headlines li {
font-size: 1.5em;
color: #000000;
transition: all 0.5s;
cursor: pointer;
}
.headlines:hover li {
/* PARENT HOVER */
opacity: 0.4;
cursor: pointer;
/* Dim all */
}
.headlines li:hover {
/* SINGLE HOVER */
opacity: 1;
/* Max one */
color: #000000;
cursor: pointer;
}
In the current code when the user hover over an element, the other elements in the menu will reduce in opacity. How can i as well do the same procedure after clicking an element.. By clicking an element it'll keep its opacity however the unclicked elements will reduce in opacity, thus highlighting the selected element.
You will need javascript for this*. For example:
var $li = $('.headlines li').click(function() {
var state = !$(this).hasClass('active');
$(this).parent().toggleClass('active', state);
$li.removeClass('active');
$(this).toggleClass('active', state);
});
ul, li {
list-style-type: none;
font-size: 1.5em;
height: 40px;
width: 150px;
text-align: right;
border-style: none;
}
.menu {
width:150px;
height: 350px;
}
.menu li {
position: relative;
right: 0;
margin: auto;
border-style:none;
}
.permahover li {
opacity: 1;
left: 10%;
}
.headlines li {
font-size:1.5em;
color:#000000;
transition: all 0.5s;
cursor: pointer;
}
.headlines:hover li,
.headlines.active li {
opacity:0.4;
cursor: pointer;
}
.headlines li:hover,
.headlines li.active {
opacity: 1;
color:#000000;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu" class="menu">
<ul class="headlines">
<li id="item1" onclick="checklist(this)">
<button onclick="myFunction()">g</button>
</li>
<li id="item2">
<button onclick="myFunction2()">a</button>
</li>
<li id="item3">b</li>
<li id="item4">c</li>
<li id="item5">d</li>
</ul>
</div>
* technically it's possible to do it with pure CSS, but the HTML structure will become complex and not that semantic.