Improve javascript code for drop down menu - javascript

The below code has two drop down menus which load container on button click and drop down closes on clicking anywhere on page. Though the window load works but the pages inside takes too much time to load even on local server obviously because my javascript code isn't the way it should. So guys what should my javascript code like so that it loads page correctly and at the same time closes drop down on clicking anywhere on page [if both drop downs are open both should close on click like in snippet].
function myFunction(event) {
event.stopPropagation();
document.getElementById("myDropdown").classList.toggle("show");
}
function myFunction2(event) {
event.stopPropagation();
document.getElementById("myDropdown2").classList.toggle("show");
}
window.onclick = function(event) {
$("#notificationContainer").load("notifications.php");
document.getElementById("myDropdown").classList.remove("show");
$("#scoreContainer").load("score.php");
document.getElementById("myDropdown2").classList.remove("show");
}
.dropdown,
.dropdown2 {
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content,
.dropdown-content2 {
display: none;
background-color: #fff;
position: absolute;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
right: 0;
}
.dropdown-content a,
.dropdown-content2 a {
padding: 10px 16px;
text-decoration: none;
display: block;
}
.show {
display: block;
}
.dropbtn {
height: 25px;
width: 50px;
border: none;
background-color: white;
background: red;
}
.dropbtn2 {
height: 25px;
width: 50px;
border: none;
background-color: white;
background: green;
}
.dropdown-content,
.dropdown-content2 {
border: 2px solid #c6c6c6;
border-top: none;
}
#notificationContainer,
#scoreContainer {
min-width: 400px;
min-height: 100px;
border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table>
<tr>
<td style="padding-right:15px;">
</td>
<td style="padding-right:15px;">
<div class="dropdown2">
<button onclick="myFunction2(event)" class="dropbtn2">one</button>
<div id="myDropdown2" class="dropdown-content2">
<div id="scoreContainer"></div>
</div>
</div>
</td>
<td style="padding-right:15px;">
<div class="dropdown">
<button onclick="myFunction(event)" class="dropbtn">two</button>
<div id="myDropdown" class="dropdown-content">
<div id="notificationContainer"></div>
</div>
</div>
</td>
</tr>
</table>
The above javascript is modified from the below single drop down menu code which loaded the page inside container instantly, but my modified version [above] takes too much time:
<script type="text/javascript">
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
window.onclick = function(event) {
$( "#notificationContainer" ).load( "notifications.php" );
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>

there is nothing inherently wrong or slow about your javascript code. have you tried inspecting how long your PHP code runs? because that's where I would start looking for the problem.

There is nothing wrong with your dropdowns. They work fine. But they lack in design and the code looks way too much for such small control. I suggest you use Bootstrap. CSS and Javascript codes are external and you just need to place your dropdown in your project by coding some HTML.
There are several different designs and the way it works simpler than what you coded. Take a look at the below example and this page for more info about it:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Bootstrap Dropdown Example</h2>
<p>Nice design, easy usage, good performance.</p>
<p><b>To open the dropdown menu, use a button or a link with a class of .dropdown-toggle and data-toggle="dropdown".</b></p>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li>THIS</li>
<li>IS</li>
<li>A DROPDOWN</li>
</ul>
</div>
</div>
</body>
</html>

Related

Dropdown menu not showing after clicking the icon (HTML)

I made a dropdown menu in my header, and when I click the moon icon (at the top right), the dropdown list doesn't show up but the function does get called when I click the icon. I've tried to use buttons but then clicking on the icon doesn't work.
Any one help me with this? I am new to this thanks.
Html:
<li>
<div class="dropdown">
<script src="./assets/js/Dropdown.js"></script>
<i class="fa-solid fa-bolt fa-lg" class="dropbtn" onclick="Dropdown()"></i>
<div id="myDropdown" class="dropdown-content">
<a><i class="fa-solid fa-moon"></i> Dark Mode</a>
<a><i class="fa-solid fa-sun"></i> Light Mode</a>
<a><i class="fa-solid fa-display"></i> System</a>
</div>
</div>
</li>
CSS:
.dropbtn {
background-color: #24252A;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
cursor: pointer;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #ddd;
}
.show {
display: block;
}
Javascript:
function Dropdown() {
document.getElementById("myDropdown").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
You have two class attributes in your icon element.
When the user clicks the icon there are two click events - the first happens on the icon itself and the show class is correctly added.
The second is the general click on the window. Having two classes confuses the JS matches function which reckons the element does not match (ie would not get selected with .dropbtn) [probably not exactly 'confused' it just looks at the first class attribute so misses the dropbtn value] so it clears the show class.
If you put all the icon's classes into one attribute value then things work OK.
function Dropdown() {
document.getElementById("myDropdown").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
.dropbtn {
background-color: #24252A;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
cursor: pointer;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {
background-color: #ddd;
}
.show {
display: block;
}
<li>
<div class="dropdown">
<script src="./assets/js/Dropdown.js"></script>
<i class="fa-solid fa-bolt fa-lg dropbtn" onclick="Dropdown()">click me</i>
<div id="myDropdown" class="dropdown-content">
<a><i class="fa-solid fa-moon"></i> Dark Mode</a>
<a><i class="fa-solid fa-sun"></i> Light Mode</a>
<a><i class="fa-solid fa-display"></i> System</a>
</div>
</div>
</li>
You could instead consider using event.stopPropagation in the first event handler which would stop the click event going through to the whole window.
I used to have that problem.
But, you don't have to reinvent the wheel, I recommend using a CSS framework, like Materialize or Bootstrap.
I recommend Materialize, it's easy to use and you just have to initialize each element you want to use.
I show you an example of navbar:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Example</title>
<!-- Google icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
</head>
<body>
<nav>
<div class="nav-wrapper">
Logo
<i class="material-icons">menu</i>
<ul class="right hide-on-med-and-down">
<li>Sass</li>
<li>Components</li>
<li>Javascript</li>
<li>Mobile</li>
</ul>
</div>
</nav>
<ul class="sidenav" id="mobile-demo">
<li>Sass</li>
<li>Components</li>
<li>Javascript</li>
<li>Mobile</li>
</ul>
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- Materialize initializers -->
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.sidenav');
var instances = M.Sidenav.init(elems);
});</script>
</body>
</html>

Multiple drop-down menus are all linking back to one

I'm a complete beginner at HTML, CSS, and JS, so forgive me.
Right now this is what I have (sorry for the length and mess):
<!DOCTYPE html>
<html>
<head>
<style>
div.ex1 {
margin: auto;
border: 0px solid transparent;
background-color: transparent;
outline: 0px solid black;
outline-offset: 0px;
width: 800px;
height:
}
div.ex2 {
margin: auto;
border: 0px solid transparent;
background-color: transparent;
outline: 1px dashed #1e58b4;
outline-offset: 25px;
width:680px;
height:
}
div.ex3 {
margin: auto;
border: 0px solid transparent;
background-color: transparent;
outline: 0px dashed #1e58b4;
outline-offset: 25px;
width:730px;
height:
}
</style>
</head>
<style>
.dropbtn {
background-color: #2b89c6;
color: white;
padding: 4px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: #2b89c6;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 100%;
overflow: auto;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content a {
color: black;
font-size: 12px;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd}
.show {display:block;}
</style>
</head>
<body>
<script>
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
</body>
<body>
<font face="courier">
<br>
<div class="ex1"><font color="black"><center><font size="2.5pt">============================================================================================<br><font size="6.5pt"><big><font color="#1e58b4">Header Header Header</font></big></font></font></font><br><font color="black"><center><font size="2.5pt">============================================================================================<!--SCIENCE--></font></font><br><div class="dropdown"><button onclick="myFunction()" class="dropbtn"><font face="courier"> Science </font></button><div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div></div> <!--ENGLISH--><div class="dropdown"><button onclick="myFunction()" class="dropbtn"><font face="courier"> English </font></button><div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div></div> <!--GEOGRAPHY--><div class="dropdown"><button onclick="myFunction()" class="dropbtn"><font face="courier"> Geography </font></button><div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div></div> <!--BUSINESS--><div class="dropdown"><button onclick="myFunction()" class="dropbtn"><font face="courier"> Business </font></button><div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div></div> <!--FRENCH--><div class="dropdown"><button onclick="myFunction()" class="dropbtn"><font face="courier"> French </font></button><div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div></div> <!--MUSIC--><div class="dropdown"><button onclick="myFunction()" class="dropbtn"><font face="courier"> Music </font></button><div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div> </div><br><font size="2.5pt">============================================================================================</font></div>
<br>
</font>
When any of the menus are clicked, only the first dropdown comes up. I know there's probably easier ways to do this, but I'd like the appearance to stay exactly as it.
If anyone could show me a fix for this, that'd be beyond helpful.
Thank You!
Your whole document needs revamping to be more up to date in terms of standards and also to make things easier in making it work.
Based on your current document;
Change all of you dropdown divs to be as so.
<div class="dropdown" onclick="myFunction(this)">
<button class="dropbtn"> Science </button>
<div id="myDropdown" class="dropdown-content">Link 1 Link 2 Link 3 </div>
</div>
Change your javascript to be as so;
<script>
function myFunction(element) {
// Here I am assuming the dropdown div to have the same child
// elements in the same order each block
element.children[1].classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropbtn')) {
var dropdowns = document.getElementsByClassName("dropdown-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
}
</script>
Add font-family: 'Courier New', Courier, monospace into the .dropbtn stylng in order to keep the font. I would advise moving all of the font tags to use this method. You should be using CSS for things like that.
Things to note;
Tags that should not really be used any more;
<font>, <center>, <big>. - These should all be achieved through CSS properties bound to classes and/or IDs.
ID should be set to a unique value for all elements that need it across the current DOM. Class is fine to be used multiple times across elements.

How to Close One Javascript Drop Down Menu When Opening Another

I'm not to familiar with JavaScript and I was hoping to get a little help with a problem I can't seem to fix. I currently have 2 Drop Down Menus on my website. One is a drop down menu for the navigation which is activated when clicking a hamburger menu icon. The second drop down is being used to show categories on my website. Currently when I click one drop down, I have to click it again in order to close it. If I click the second drop down without closing the first both will remain visible. What I would like to happen is two things. First I would like it so that if a user clicks anywhere outside of the div for the drop down menu it automatically closes. The second thing I would like to see happen is only have one drop down menu visible at a time. So if I click one and another drop down is open I want it to be closed. Hopefully I explained this well. Now onto the code I'm using.
The following is within my head.
<script>
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function DropDownMenuNavigation() {
document.getElementById("b2DropDownMenuNav").classList.toggle("show");
}
function DropDownMenuCategory() {
document.getElementById("b2DropDownMenuCat").classList.toggle("show");
}
</script>
Then I use this as the button to activate the navigation drop down menu. This is included within my body.
<div class="dropbtn" style="float: left;">
<button onclick="DropDownMenuNavigation()" class="dropbtn">☰ MENU</button>
</div>
and this what I use to include my category drop down menu.
<div class="dropbtn" style="float: left;">
<button onclick="DropDownMenuCategory()" class="dropbtn">CATEGORIES</button>
</div>
Now lastly is the css I use just on the off chance that helps any.
/* Dropdown Button */
.dropbtn {
background-color: #0066a2;
color: white;
padding: 1px;
font-size: 15px;
font-weight: bold;
border: none;
cursor: pointer;
}
.dropbtn a {
color: #FFFFFF;
text-decoration: none;
font-size: 15px;
font-weight: bold;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
float: left;
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #0066a2;
min-width: 260px;
max-width: 960px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content a {
color: #000000;
text-decoration: none;
}
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {display:block;}
So what would be the best method to go about doing what I'm asking? Could someone maybe lend me a hand and point me in the right direction. Thanks a lot and I appreciate any help you could lend me.
The onclick attribute shouldn’t include the (). It should look like this:
<button onclick="DropDownMenuNavigation" class="dropbtn">☰ MENU</button>
Or—even better—don’t put the event listener inline, put it in the script.
Also, remove the “show” class from the other dropdown when the button is pressed.
See here:
document.getElementById('menudropbtn').addEventListener('click', function () {
document.getElementById('b2DropDownMenuNav').classList.toggle('show')
document.getElementById('b2DropDownMenuCat').classList.remove('show')
})
document.getElementById('categoriesdropbtn').addEventListener('click', function () {
document.getElementById('b2DropDownMenuCat').classList.toggle('show')
document.getElementById('b2DropDownMenuNav').classList.remove('show')
})
/* Dropdown Button */
.dropbtn {
background-color: #0066a2;
color: white;
padding: 1px;
font-size: 15px;
font-weight: bold;
border: none;
cursor: pointer;
}
.dropbtn a {
color: #FFFFFF;
text-decoration: none;
font-size: 15px;
font-weight: bold;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
float: left;
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #0066a2;
min-width: 260px;
max-width: 960px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content a {
color: #000000;
text-decoration: none;
}
/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {
display: block;
}
<div class="dropbtn" style="float: left;">
<button class="dropbtn" id="menudropbtn">☰ MENU</button>
<div class="dropdown">
<div class="dropdown-content" id="b2DropDownMenuNav">
<a>Something</a>
</div>
</div>
</div>
<div class="dropbtn" style="float: left;">
<button class="dropbtn" id="categoriesdropbtn">CATEGORIES</button>
<div class="dropdown">
<div class="dropdown-content" id="b2DropDownMenuCat">
<a>Something else</a>
</div>
</div>
</div>
To do this, you can add custom JS functions that will open dropdowns based on element ID, and when one dropdown is opened, all others will be closed. You can create a function that closes all the dropdowns. Then, in your "open" function, call the "close_all" function first.
Here's a working snippet.
// Functions for Interactive File Menu Bar
// - Click Butoon to Open Dropdown
// - Clicking one dropdown closes all other
// - Clicking outside the file menu bar will close all the dropdown.
function open_dropdown(element_id) {
console.log('Opening Dropdown:', element_id)
close_all_dropdowns()
document.getElementById(element_id).style.display = 'block';
}
// Close the dropdown if the user clicks outside of it
function close_dropdown(element) {
console.log('I am closing dropdown:', element)
element.style.display = 'none'
}
// Close all dropdowns.
function close_all_dropdowns() {
var dropdowns = document.getElementsByClassName('dropdown-content')
for (var i = 0; i < dropdowns.length; i++) {
close_dropdown(dropdowns[i]);
}
}
// Close all dropdowns when clicking outside.
window.onclick = function (e) {
if (!e.target.matches('.dropbtn')) {
close_all_dropdowns()
}
}
/* Styles for the File Menu Bar. */
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f1f1f1;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/98.css">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<title>RetroNet</title>
</head>
<body>
<div class="window" style="width: 100%">
<div class="title-bar">
<div class="title-bar-text">Welcome to RetroNet!</div>
<div class="title-bar-controls">
<button aria-label="Minimize"></button>
<button aria-label="Maximize"></button>
<button aria-label="Close"></button>
</div>
</div>
<!-- Main menu -->
<div class="window-body">
<div class="dropdown">
<button class="dropbtn" onclick="open_dropdown('dd_file')">File</button>
<div class="dropdown-content" id="dd_file">
Open
Close
Settings
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="open_dropdown('dd_edit')">Edit</button>
<div class="dropdown-content" id="dd_edit">
Cut
Copy
Paste
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="open_dropdown('dd_view')">View</button>
<div class="dropdown-content" id="dd_view">
Toggle CSS
Toggle Javascript
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="open_dropdown('dd_tools')">Tools</button>
<div class="dropdown-content" id="dd_tools">
Not Decided
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="open_dropdown('dd_favorite')">Favourties</button>
<div class="dropdown-content" id="dd_favorite">
Add New Favorite
Add this Page to Favorites
Show Favorites
</div>
</div>
<div class="dropdown">
<button class="dropbtn" onclick="open_dropdown('dd_help')">Help</button>
<div class="dropdown-content" id="dd_help">
README
</div>
</div>
</div>
</div>
</body>
</html>
Maybe the following code can help. You can use custom event to have module items (like menu, popup or such) communicate to each other.
If a menu button is clicked then you can dispatch a custom event. Any other item on the page may do something according to what this event is (like pausing a game when a main menu is opened).
// find menu-content in item (=menu-button) and return
// "none" if menu-content.style.display is "block"
// "block" if menu-content.style.display is not "block"
const toggle =
(item) => {
const content =
item.querySelector("[x-role=\"menu-content\"]");
return content.style.display === "block"
? "none"
: "block"
}
;
// set menu-content found in item (=menu-button) to
// none or block
const changeDisplay =
(item,display) =>
item.querySelector("[x-role=\"menu-content\"]")
.style.display = display;
// when menu-button is clicked
const menuButtonClicked =
e => {
//get the toggled content style
// if current style is block then
// toggled is none and vice versa
const style = toggle(e.target);
//hide all menus, in the for each we
// added an event listener for "menu-click" event
// the listener will hide the menu
var evt = new Event("menu-click",{});
document.body.dispatchEvent(evt);
//set style of the current
changeDisplay(e.target,style);
}
;
//for each menu-botton role
// I am not using css selectors on class, class is for style,
// user defined properties can be used for behavior.
// If you mix this up then you can break style, behavior
// or both when changing behavior or style
document.querySelectorAll("[x-role=\"menu-button\"]")
.forEach(
x => {
//when clicked let menuButtonClicked handle it
x.addEventListener(
"click"
,menuButtonClicked
);
//listen to custom event called "menu-click"
// set display to none when this happens
// if you were to dynamically add and remove
// menu items then you should remove the event
// listeners when you remove the menu
document.body.addEventListener(
"menu-click"
,e => changeDisplay(x,"none")
);
}
)
;
.menu-button {
cursor: pointer;
}
.menu-content {
display:none;
}
<div class="menu-button" x-role="menu-button">
menu1
<div class="menu-content" x-role="menu-content">
<ul>
<li>one</li>
<li>two</li>
</ul>
</div>
</div>
<div class="menu-button" x-role="menu-button">
menu2
<div class="menu-content" x-role="menu-content">
<ul>
<li>three</li>
<li>four</li>
</ul>
</div>
</div>
<div class="menu-button" x-role="menu-button">
menu3
<div class="menu-content" x-role="menu-content">
<ul>
<li>five</li>
<li>six</li>
</ul>
</div>
</div>

Mobile drop-down menu toggle "working" but never visible

I'm trying to create a pretty basic mobile drop-down menu that expands on click for the top-right nav of this codepen portfolio page project for Free Code Camp. The menu never shows up, but when I inspect the element it seems like the javascript function is actually working, with the "show" CSS class being added and removed to the mobileNavDrop div.
The invisible menu also seems to be located on the page where it's supposed to be, as can be seen in this screenshot using the inspect element tool:
Invisible drop-down menu highlighted with inspect element tool
I've tried pushing it all the way forward with z-index and making the banner invisible to see if it's hiding behind things, but it isn't. I even tried just having the menu start as visible rather than with "display: none;" and it still doesn't show up on the page.
The advice I've gotten elsewhere is to just use jquery and bootstrap, but I'd hoped to understand things more by trying to just write everything from scratch. So it's possible something I wrote for the responsive layout is conflicting?
Here's at least the sections of code that I thought would be relevant. Thanks!
HTML
<div class='container-navbar'>
<div class='navbar'>
<div class='row'>
<div class='col-sm-2 col-md-1'>
<ul class='nav-left'>
<li class='header-button'><a href='http://www.freecodecamp.com/davallerr' target='_blank'>davallerr</a></li>
</ul>
</div>
<div class='col-sm-2 col-md-3'>
<div class='mobile-nav'>
<i onclick='mobileNavDrop()' class='fa fa-bars mobile-nav-icon'></i>
<div id='mobileNavDrop' class='mobile-nav-drop'>
<a href='#about'>about</a>
<a href='#portfolio'>the work</a>
<a href='#contact'>contact</a>
</div>
</div>
<ul class='nav-right'>
<li><a href='#about'>about</a></li>
<li><a href='#portfolio'>the work</a></li>
<li><a href='#contact'>contact</a></li>
</ul>
</div>
</div>
</div>
</div>
CSS
.mobile-nav-icon {
padding: 1.25em;
}
.mobile-nav-icon:hover, .mobile-nav-icon:focus {
background: #40514f;
color: #fff;
}
.mobile-nav {
position: relative;
display: inline-block;
float: right;
overflow: visible;
}
.mobile-nav-drop {
display: none;
position: absolute;
right: 0;
background: #ccc;
min-width: 10em;
box-shadow: 0 0 .25em 0 rgba(0,0,0,.2);
}
.show {
display: block;
}
.mobile-nav-drop a {
color: #000;
padding: 1em;
display: block;
}
.mobile-nav-drop a:hover {
background: #aaa;
}
JS
function mobileNavDrop() {
document.getElementById('mobileNavDrop').classList.toggle('show');
}
window.onclick = function(event) {
if (!event.target.matches('.mobile-nav-icon')) {
var dropdowns = document.getElementsByClassName('mobile-nav-drop');
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
};
You need:
.show {
display: block;
position: absolute; /* add this line, */
top: 0; /* and this one */
}
Plus, make sure the overflow is visible in every container of that nav that might not be large enough to contain the drop-down menu.
You are probably not seeing the icon because you have not included the FontAwesome library for the icon (fa fa-bars).
try adding this cdn reference to your <head>:
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
or download and install a local copy.
function mobileNavDrop() {
document.getElementById('mobileNavDrop').classList.toggle('show');
}
window.onclick = function(event) {
if (!event.target.matches('.mobile-nav-icon')) {
var dropdowns = document.getElementsByClassName('mobile-nav-drop');
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}else
{
openDropdown.classList.contains('show');
}
}
}
};
.mobile-nav-icon {
padding: 1.25em;
}
.mobile-nav-icon{
background-color:grey;
}
.mobile-nav-icon:hover, .mobile-nav-icon:focus {
background: #40514f;
color: darkgrey;
}
.mobile-nav {
position: relative;
display: inline-block;
float: right;
overflow: visible;
}
.mobile-nav-drop {
position: absolute;
right: 0;
background: #ccc;
min-width: 10em;
box-shadow: 0 0 .25em 0 rgba(0,0,0,.2);
}
.hide{
display: none;
}
.show {
display: block;
}
.mobile-nav-drop a {
color: #000;
padding: 1em;
display: block;
}
.mobile-nav-drop a:hover {
background: #aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class='container-navbar'>
<div class='navbar'>
<div class='row'>
<div class='col-sm-4 col-md-1'>
<ul class='nav-left'>
<li class='header-button'><a href='http://www.freecodecamp.com/davallerr' target='_blank'>davallerr</a></li>
</ul>
</div>
<div class='col-sm-4 col-md-3'>
<div class='mobile-nav'>
<div onclick='mobileNavDrop()' class='fa fa-bars mobile-nav-icon'></div>
<div id='mobileNavDrop' class='mobile-nav-drop hide'>
<a href='#about'>about</a>
<a href='#portfolio'>the work</a>
<a href='#contact'>contact</a>
</div>
</div>
<ul class='nav-right'>
<li><a href='#about'>about</a></li>
<li><a href='#portfolio'>the work</a></li>
<li><a href='#contact'>contact</a></li>
</ul>
</div>
</div>
</div>
</div>
In your javascript. I added an else statement so it toggles back and forth.
Your statement only removes 'show' but does not add it back.

Is it possible to run a js function by means of a dropdown CSS menu?

original post
Is it possible to run a js function by means of a dropdown CSS menu ?
I would realize a menu, looking like the habitual navigational ones, but aimed, instead, to run a different javascript function on each item, or, I think it's the same thing, to pass a different argument to a function and run it.
Is it practicable ? Googling, I pick the opposite (dropdown menu via js) ...
addendum
Thanks to the advice provided by some courteous members, I have solved my problem, attaching an event handler to each item of the menu. Therefore I post here the code. Thanks again.
<HTML>
<HEAD>
<TITLE></TITLE>
<style>
<!--http://www.w3schools.com/css/css_dropdowns.asp-->
.dropbtn {
background-color: #4CAF50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown-content a:hover {background-color: #f1f1f1}
.dropdown:hover .dropdown-content {
display: block;
}
.dropdown:hover .dropbtn {
background-color: #3e8e41;
}
#myvar{
margin-top: 200px;
}
</style>
<script type="text/javascript">
function setVar(arg){
document.getElementById("myvar").innerHTML = arg;
}
</script>
<script>
var x = 0;
</script>
</HEAD>
<BODY onLOad="setVar(x)">
<div class="dropdown">
<span>menu</span>
<div id = "menudd" class="dropdown-content">
<p onClick="setVar(1)">item 1</p>
<p onClick="setVar(2)">item 2</p>
<p onClick="setVar(3)">item 3</p>
</div>
</div>
<p onClick="setVar(3)">again 3</p>
<P id="myvar"></P>
</BODY>
</HTML>
I don't know what you mean by a "CSS menu". You don't create menus with CSS; you create them with HTML. You use CSS to style them and make them look menu-like.
All HTML-based web applications are based on attaching behaviors (implemented in JS) to HTML elements (such as buttons or menu items).
Attach an event handler for the click event to the HTML element that represents a particular menu item, and provide whatever function you want to execute.

Categories

Resources