This is my first time writing a JS function. I am trying to get the navigation bar to open when the hamburger is clicked but it's not working. I have attached my HTML and JS.
It works when I don't allow the function to have any parameter and instead manually write "nav" where nav_type is, so I'm not sure why it's not working.
The code:
/* Toggle between showing and hiding the navigation menu links when the user clicks on the hamburger menu / bar icon */
function myFunction(nav_type) {
var i;
var x;
for (i = 1; i < 6; i++) {
x = document.getElementById(nav_type + i);
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
}
<nav aria-label="Main Navigation" class="topnav">
<a aria-hidden="true" href="javascript:void(0);" ; class="menu show-mobile" onclick="myFunction(" nav ")">
<img src="img/menu-icon.svg" alt="toggle menu" />
</a>
<ul class="topnav">
<li>Home</li>
<li>Humans</li>
<li><a href="other/other.html" id="nav2">Plants, Animals, the Universe, and Other
</a></li>
<li class="dropdown" id="nav3">
<button class="dropbtn" id="nav4" onclick="myFunction(" drp ")">More
<img src="img/down-arrow.svg" alt="dropdown arrow" class="dropdown-icon icon"/>
</button>
<ul class="topnav dropdown-content">
<li>Presentations</li>
<li>About Islam</li>
<li>Contact Us</li>
</ul>
</li>
</ul>
</nav>
You are using multiple quotations marks together, the parser is considering the first pair of quotation mark to me the value of the onload attribute, which is "myFunction(" and the rest are considered gibberish.
Use double quotations (") and single quotations (') together to avoid this error
onclick="myFunction('nav')">
Similarly
onclick="myFunction(" drp ")"
Just use HTMLElement.classList.toggle(class)
document.querySelector('#navShow').addEventListener('click', () => {
document.querySelector('ul.topnav').classList.toggle('show');
});
ul.topnav {
display: none;
}
ul.topnav.show {
display: block;
}
<nav aria-label="Main Navigation" class="topnav">
<a id="navShow" aria-hidden="true" href="#"; class="menu show-mobile">
Menu
</a>
<ul class="topnav">
<li>Home</li>
<li>Humans</li>
<li><a href="other/other.html" id="nav2">Plants, Animals, the Universe, and Other
</a></li>
<li class="dropdown" id="nav3">
<button class="dropbtn" id="nav4" onclick="myFunction("drp")">More
<img src="img/down-arrow.svg" alt="dropdown arrow" class="dropdown-icon icon"/>
</button>
<ul class="topnav dropdown-content">
<li>Presentations</li>
<li>About Islam</li>
<li>Contact Us</li>
</ul>
</li>
</ul>
</nav>
For a more modern approach dispose of Javascript for the function altogether.
Here we use a label and a hidden checkbox combined with CSS to control our menu show/hide.
#chkNav {
display: none;
}
.nav-bar {
display: block;
width: 30px;
height: 0px;
margin-bottom: 2px;
border: 3px solid black;
}
ul.topnav {
display: none;
}
#chkNav:checked + ul.topnav {
display: block;
}
<nav aria-label="Main Navigation" class="topnav">
<label for="chkNav" aria-label="show nav">
<span class="nav-bar"></span>
<span class="nav-bar"></span>
<span class="nav-bar"></span>
</label>
<input type="checkbox" id="chkNav" />
<ul class="topnav">
<li>Home</li>
<li>Humans</li>
<li><a href="other/other.html" id="nav2">Plants, Animals, the Universe, and Other
</a></li>
<li class="dropdown" id="nav3">
<button class="dropbtn" id="nav4" onclick="myFunction("drp")">More
<img src="img/down-arrow.svg" alt="dropdown arrow" class="dropdown-icon icon"/>
</button>
<ul class="topnav dropdown-content">
<li>Presentations</li>
<li>About Islam</li>
<li>Contact Us</li>
</ul>
</li>
</ul>
</nav>
Related
Basically, I want on the click event to remove the class active form the current element and move it the clicked one. I wrote the following code and in the desktop mode it work just fine but in the mobile version it doesn't remove the class from the "old active" element BUT if I click on the already active element the behaviour of my function goes back to normal.
HTML
<header>
<!-- the ul in the is visible untill 1200px, after that the "mobile-mene" make visibile a hamburger icon and the "menu" is invisible untill the hamburger is clicked -->
<nav>
<a href="#home">
<span class="logo">
Ernesto Dovizioso
</span>
</a>
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
<div class="mobile-menu">
<i class="fas fa-bars"></i>
</div>
</nav>
<!-- this is invisible untill the hb menu il clicked -->
<div class="menu">
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
</div>
</header>
JS
const ul = document.querySelectorAll("header ul li");
ul.forEach(li => {
li.addEventListener("click", activeLiChange);
});
function activeLiChange(){
let activeLi = document.querySelector("li.active");
console.log(this.innerHTML);
console.log(activeLi.innerHTML);
if(!this.isEqualNode(activeLi)){
this.classList.add("active");
activeLi.classList.remove("active");
}
}
The reason it isn't working on mobile is because you are using querySelector which only returns the first instance of .active which is in your non-mobile menu. You'll need to use querySelectorAll('li.active') and iterate over the resulting NodeList.
Using your code as is here is a fix:
const ul = document.querySelectorAll("header ul li");
ul.forEach(li => {
li.addEventListener("click", activeLiChange);
});
function activeLiChange(){
const activeLi = document.querySelectorAll("li.active");
activeLi.forEach(li => {
if(!this.isEqualNode(li)){
this.classList.add("active");
li.classList.remove("active")
}
});
}
.active {
color: tomato;
}
<header>
<nav>
<a href="#home">
<span class="logo">
Ernesto Dovizioso
</span>
</a>
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
<div class="mobile-menu">
<i class="fas fa-bars"></i>
</div>
</nav>
<!-- this is invisible untill the hb menu il clicked -->
<div class="menu">
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
</div>
</header>
But you can simplify this by attaching the listener to each ul element instead of every li. Then in your activeLiChange() function use target (the li) and currentTarget (the ul) to address the relevant menu list.
const ul = document.querySelectorAll("header ul");
ul.forEach(list => {
list.addEventListener("click", activeLiChange);
});
function activeLiChange(e){
const activeLi = e.currentTarget.querySelector("li.active");
if(!e.target.isEqualNode(activeLi)){
e.target.classList.add("active");
activeLi.classList.remove("active");
}
}
.active {
color: tomato;
}
<header>
<nav>
<a href="#home">
<span class="logo">
Ernesto Dovizioso
</span>
</a>
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
<div class="mobile-menu">
<i class="fas fa-bars"></i>
</div>
</nav>
<!-- this is invisible untill the hb menu il clicked -->
<div class="menu">
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
</div>
</header>
how can one add a dropdown caret to the account link in the html code below
.
.
.
<nav>
<ul id="menu">
<li class="home"><a href= "home.html" class="menu" ><h3>Home</h3></a></li>
<li class="news"><h3>News</h3></li>
<li class="account"><h3>Account</h3></li>
</ul>
</nav>
There are many ways to do this. Here is a way using only CSS and the ::after psuedo element.
.dropdown-toggle {
display: flex;
align-items: center;
}
.dropdown-toggle::after {
content: "⬇️";
margin-left: 10px;
}
<nav>
<ul id="menu">
<li class="home"><a href="home.html" class="menu">
<h3>Home</h3>
</a></li>
<li class="news"><a href="news.html" class="menu" target="_blank">
<h3>News</h3>
</a></li>
<li class="account"><a href="#" class="menu dropdown-toggle" target="_blank" data-toggle="dropdown">
<h3>Account</h3>
</a></li>
</ul>
</nav>
I am having a problem on how to make an overlay working as I want. The problem is that when I click on the burger button, the overlay covers the bootstrap navbar and even the sliding menu. What I want is that the overlay only affects the HTML body, not including the navbar and the sidebar. Moreover, I want to disable the overlay through the same button but I dont know how to manage that too. Any help. Code is below.
function on() {
document.getElementById("overlay").style.display = "block";
}
function off() {
document.getElementById("overlay").style.display = "none";
}
//mobile menu slide from the left
$('[data-toggle="slide-collapse"]').on('click', function() {
$navMenuCont = $($(this).data('target'));
$navMenuCont.animate({'width':'toggle'}, 350);
});
#overlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2;
cursor: pointer;
}
<body>
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="pull-left navbar-toggle" data-toggle="slide-collapse" data-target="#myNavbar" onclick="on()" onclick="off()">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Logo</a>
</div>
<div class="collapse navbar-collapse" id="">
<ul class="nav navbar-nav navbar-right">
<li>HOME</li>
<li>BAND</li>
<li>TOUR</li>
<li>CONTACT</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">MORE
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Merchandise</li>
<li>Extras</li>
<li>Media</li>
</ul>
</li>
<li><span class="glyphicon glyphicon-search"></span></li>
</ul>
</div>
</div>
</nav>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li>HOME</li>
<li>BAND</li>
<li>TOUR</li>
<li>CONTACT</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">MORE
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Merchandise</li>
<li>Extras</li>
<li>Media</li>
</ul>
</li>
<li><span class="glyphicon glyphicon-search"></span></li>
</ul>
</div>
<div id="overlay"></div>
</body>
You're not creating a stacking context for your navbars.
A stacking context is formed, anywhere in the document, by any element
in the following scenarios:
Element with a position value "absolute" or "relative" and
z-index value other than "auto".
You need to add:
navbar {
z-index: 5;
}
#myNavbar {
z-index: 5;
position: relative;
}
This will allow them to stack relative to the body and the overlay and whatever else you have. You might also move the overlay above them in the DOM, just so I guess semantically (?) it would be stacked before your navbars. But that's probably not required.
I knew javaScript but I'm not used to it as I'm more focus on creating UI design. So decided to take up some short courses and then I've encountered this problem. There should be dropdown which consist of 4 items to choose: red, blue, green, yellow. If a user choose a color let's say yellow, the div box underneath will become yellow. I used Bootstrap for this by the way.
My code goes something like this ` Dropdown 1
<ul class="dropdown-menu">
<li id="red">Red
</li>
<li>Blue
</li>
<li>Green
</li>
<li>Yellow
</li>
</ul>
`
Full code resides here
http://jsfiddle.net/0c4dbr9t/7/
Try this simple code
Demo
Code:
<div class="btn-group"> <a class="btn " href="#">Dropdown 1</a>
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>
<ul class="dropdown-menu">
<li data-color="red">Red
</li>
<li data-color="blue">Blue
</li>
<li data-color="green">Green
</li>
<li data-color="yellow">Yellow
</li>
</ul>
</div>
<div id ="box"><div>
$( document ).ready(function() {
$('.dropdown-menu li').click(function(){
var color = $(this).data("color");
$("#box").css('background-color',color);
});
});
Please let me know if this is what you needed..
html
<div class="btn-group"> <a class="btn " href="#">Dropdown 1</a>
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>
<ul id="dd" class="dropdown-menu">
<li>Red
</li>
<li>Blue
</li>
<li>Green
</li>
<li>Yellow
</li>
</ul>
</div>
<div id ="box"><div>
css
#box {
margin-top: 20px;
background-color: #000;
padding: 50px;
}
js
var ul = document.getElementById('dd');
ul.addEventListener("click", changeColor, false);
function changeColor (e) {
if(e.target.nodeName == "A") {
document.getElementById("box").style.background =e.target.innerHTML;
}
}
Using simple javascript:
<div class="btn-group"> <a class="btn " href="#">Dropdown 1</a>
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>
<ul class="dropdown-menu">
<li id="red">Red
</li>
<li>Blue
</li>
<li>Green
</li>
<li>Yellow
</li>
</ul>
</div>
<div id ="box"> Some Text <div>
<script>
var menu = document.querySelector("ul.dropdown-menu");
menu.onclick = function(evt) {
console.log(evt.target.innerText)
document.getElementById("box").style.backgroundColor = evt.target.innerText;
}
</script>
The animation of the drop down menu gets stuck while it is supposed to create a slide effect animation
JSFiddle link: http://jsfiddle.net/uqcLn/73/
This is the css that may have caused the problem but it is necessary to my code
(it makes the bottom div's of my site stationary) so it cannot be changed.
#nav ul ul {
display: none;
z-index: 1000;
}
#nav ul li:hover > ul {
position: absolute;
display: block;
}
With this your code is already more valid
<div id="top_menu">
<div id="logo"><img src="images/logo.png"></div>
<div id="nav">
<ul>
<li class="links_wrapper">ABOUT US
<ul class="dropdown">
<li>About us</li>
<li>Our Vision</li>
<li>Our Technology</li>
<li>Our Customers</li>
</ul></li>
<li class="links_wrapper">SOLUTIONS
<ul class="dropdown">
<li> Solutions</li>
<li>General Descreption</li>
<li>Detailed Descreption</li>
</ul></li>
<li class="links_wrapper">CUSTOMERS
<ul class="dropdown">
<li> Solutions</li>
<li>General Descreption</li>
<li>Detailed Descreption</li>
</ul></li>
<li class="links_wrapper">CONTACT US
<ul class="dropdown">
<li>Solutions</li>
<li>General Descreption</li>
<li> Descreption</li>
</ul></li>
</ul>
<div id="login">LOGIN</div>
<div id="lang_btn">He En
</div><!--close nav-->
</div><!--top menu-->
You should from time to time test your code inside W3C's validator
http://validator.w3.org/