Having trouble hiding menu when resizing and when button is pressed - javascript

I'm using this code:
#media screen and (max-width: 850px) {
#side-menu {
display: none;
}
button {
display: block;
}
}
to hide my side menu and display a button when I resize window. I also want to show and hide menu when the button is pressed. To do that I'm using this code:
function showMenu() {
var sideMenu = document.getElementById("side-menu");
if (sideMenu.style.display === "none") {
sideMenu.style.display = "block";
}
else {
sideMenu.style.display = "none";
}
}
When I hide with button the menu does not reappear when I resize window. I believe this is happening because the javaScript changes the primary style to display: none, so once it's out of range it applies the primary style. Now it's display: none so it doesn't appear again. How can I get it to work how I intend it to? Also, it takes two clicks to show menu for some reason.
<ul id="side-menu">
<li>example1</li>
<li>example2</li>
<li>example3</li>
<li>example4</li>
</ul>
html just in case you need it.

You must check if the display === "block" first to fix the multiple click issue.
Included media query to manage window width that is greater than 850px to show list and hide button.
EDIT: updated snippet to use the list provided in the original question.
function showMenu() {
var sideMenu = document.getElementById("side-menu");
if (sideMenu.style.display === "block") {
sideMenu.style.display = "none";
}
else {
sideMenu.style.display = "block";
}
}
#media screen and (min-width: 850px) {
#side-menu {
display: block;
}
button {
display: none;
}
}
#media screen and (max-width: 850px) {
#side-menu {
display: none;
}
button {
display: block;
}
}
<div id="side-menu">
<ul>
<li>example1</li>
<li>example2</li>
<li>example3</li>
<li>example4</li>
</ul>
</div>
<button onclick="showMenu()">click me</button>

//swap none with block to fix double button press
function showMenu() {
var sideMenu = document.getElementById("side-menu");
if (sideMenu.style.display === "block") {
sideMenu.style.display = "none";
}
else {
sideMenu.style.display = "block";
}
}
/* add this to fix menu show*/
#media screen and (min-width: 850px) {
#side-menu {
display: block !important;
}
button {
display: none;
}
}
#media screen and (max-width: 850px) {
#side-menu {
display: none;
}
button {
display: block;
}
}
<div id="side-menu">
<ul>
<li>example1</li>
<li>example2</li>
<li>example3</li>
<li>example4</li>
</ul>
</div>
<button onclick="showMenu()">click me</button>
Thanks ksa and StackSlave

Related

How to hide navigation bar on link click?

I have 3 buttons and a responsive hamburger menu. Everything works as expected, but I can't think of a way to make a navigation bar go away as soon as I click on a button.
The program is supposed to work like this: clicking hamburger menu activates 3 buttons, whenever user clicks on any of those 3 buttons it hides the buttons and only leaves the button that was clicked.
This is the wanted outcome:
This is my code so far.
html:
<div class="selectSection">
<button type="button" data-number="1" class="active">1</button>
<button type="button" data-number="2">2</button>
<button type="button" data-number="3">3</button>
</div>
<div class="hamburger">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
<div>
<div class="content" data-number="1">
<p>1st page</p>
</div>
<div class="content" data-number="2">
<p>2nd page</p>
</div>
<div class="content" data-number="3">
<p>3rd page</p>
</div>
</div>
css
.content:not(:first-child) {
display: none;
}
.active {
color: orange !important;
}
.hamburger {
display: none;
}
#media all and (max-width: 800px) {
.hamburger {
display: inline-block;
cursor: pointer;
z-index: 7;
}
.hamburger .line {
width: 30px;
height: 3px;
background: black;
margin: 6px 0px;
}
.selectSection {
display: none;
overflow: hidden;
}
.selectSection.active {
display: block;
}
}
js
// change active class, show the clicked element only and hide the others
// grab all the buttons
let Buttons = document.querySelectorAll(".selectSection button");
// loop through the buttons using for..of
for (let button of Buttons) {
// listen for a click event
button.addEventListener("click", (e) => {
// et = event target
const et = e.target;
// slect active class
const active = document.querySelector(".active");
// check for the button that has active class and remove it
if (active) {
active.classList.remove("active");
}
// add active class to the clicked element
et.classList.add("active");
// select all classes with the name content
let allContent = document.querySelectorAll(".content");
// loop through all content classes
for (let content of allContent) {
// display the content if the class has the same data-attribute as the button
if (
content.getAttribute("data-number") ===
button.getAttribute("data-number")
) {
content.style.display = "block";
}
// if it's not equal then hide it.
else {
content.style.display = "none";
}
}
});
}
hamburger = document.querySelector(".hamburger");
hamburger.onclick = function () {
navBar = document.querySelector(".selectSection");
navBar.classList.toggle("activate");
};
This is the demo:
https://codepen.io/f4kermak3r/pen/ExRPKzJ
you are using the wrong css class in your js file. At line 44, you must change navBar.classList.toggle("activate") to navBar.classList.toggle("active"). That should work.

Basic jquery toggleClass not working in es6 class

I have a menu that I want to show when an icon is clicked. I have the menu hidden by default when the page loads. I am using jQuerys toggleClass() method. When I click the icon the show class is never added to the .menu. The menu class highlights in the browser dev tools each time I click but no class is being added to it.
If I use the addClass() method then the class is added but I want to be able to toggle the show class so the menu is able to be shown and hidden while clicking the same icon/element.
HTML
<i class="fa fa-ellipsis-v"></i>
<div class="menu">
<div id="context-menu">
Item 1
Item 2
Item 3
Item 4
</div>
</div>
Menu.js
class Menu {
constructor() {
this.menu = document.querySelector('.menu');
this.ellipsis = document.querySelector('.fa.fa-ellipsis-v');
this.callEvent();
}
callEvent() {
this.ellipsis.addEventListener('click',this.showMenu.bind(this));
}
showMenu(e){
e.preventDefault();
$('.menu').toggleClass('show');
}
}
CSS
.menu {
display:none;
}
.show{
display:block;
}
This shouldn't be an answer but it really can't be a comment. I used your code, added a little css to make things viewable and guessed at the html (but that shouldn't make a difference). The code works as expected.
class Menu {
constructor() {
this.menu = document.querySelector('.menu');
this.ellipsis = document.querySelector('.fa.fa-ellipsis-v');
this.callEvent();
}
callEvent() {
this.ellipsis.addEventListener('click',this.showMenu.bind(this));
}
showMenu(e){
e.preventDefault();
$('.menu').toggleClass('show');
}
}
var menu = new Menu();
.menu {
display:none;
background-color: blue;
height: 100px;
width: 100px;
}
.show{
display:block;
}
.fa-ellipsis-v {
font-weight: bold;
font-size: 20px;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu"></div>
<span class="fa fa-ellipsis-v">...</span>
See below. I'm using display:flex instead of display:block for layout purposes.
class Menu {
constructor() {
this.menu = document.querySelector('.menu');
this.ellipsis = document.querySelector('.fa.fa-ellipsis-v');
this.callEvent();
}
callEvent() {
this.ellipsis.addEventListener('click', () => {
$('.menu').toggleClass('show');
});
}
}
const dummy = new Menu();
.menu {
display: none;
}
.show {
display: flex;
}
nav {
display: flex;
}
ul {
list-style: none;
margin: 0;
justify-content: space-around;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<nav>
<i class="fa fa-ellipsis-v"></i>
<ul class="menu">
<li>This</li>
<li>is</li>
<li>a</li>
<li>menu</li>
</ul>
</nav>

Responsive navbar with dropdown mobile hamburger icon disappears when toggled

The drop-down menu works fine on the laptop.
On the mobile device it comes up as a single bar. When I select the hamburger icon, the drop-down are displays as they should. When I select one of the buttons, the link works. But if I instead hit the hamburger icon the second time, the hamburger and complete bar disappear. The only way to bring the navbar back is to do a browser refresh.
I have tried several responsive navbar code selections and this is the closest to a working responsive navbar.
HTML code
...
<nav>
<div class="topnav" id="myTopnav">
Home
New Here
<div class="dropdown">
<button class="dropbtn">Ministries
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content">
Adult
Member Care
Outreach
Youth
</div>
</div>
Donate
...
Contact
About
☰
</div>
</nav>
CSS code
...
/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */
#media screen and (max-width: 600px) {
.topnav a:not(:first-child), .dropdown .dropbtn {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
#media screen and (max-width: 600px) {
.topnav.responsive {position: relative;}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
.topnav.responsive .dropdown {float: none;}
.topnav.responsive .dropdown-content {position: relative;}
.topnav.responsive .dropdown .dropbtn {
display: block;
width: 100%;
text-align: left;
}
}
...
javascript code
/* Toggle between showing and hiding the navigation menu links when the user clicks on the hamburger menu / bar icon */
function navBarIcon() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
//* Loop through all dropdown buttons to toggle between hiding and showing its dropdown content - This allows the user to have multiple dropdowns without any conflict */
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
As I mentioned, the code works except when the hamburger icon is hit a second time to close the navbar. It goes beyond closing, but rather disappears.
Modified javascript and it works now.
/* Toggle between showing and hiding the navigation menu links when the user clicks on the hamburger menu / bar icon */
function navBarIcon() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
//* Loop through all dropdown buttons to toggle between hiding and showing its dropdown content - This allows the user to have multiple dropdowns without any conflict */
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}

Add display property to accordion onload depending on resolution

I'm using the W3C accordion on my website, and only want the accordion to be active when the page is under 768px. So far, I have the script adjusted so that the "panel" div's will toggle, but they initially are displayed, rather than hidden. Is there a line I can add to the code to initially hide the panel div's when the resolution is under 768px? I've tried adding display:none to the element in the css sheet, but the toggle script won't override it.
Hope this makes sense!
<script>
if (screen.width < 768) {
var acc = document.getElementsByClassName("filterAccordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.display === "block") {
panel.style.display = "none";
} else {
panel.style.display = "block";
}
});
}
}
</script>
I have a feeling you can manage this in CSS..
#media only screen and (max-width: 768px) {
.filterAccordion {
display: none;
}
}
As for the accordian and mentioned by Quentin.. W3Schools is probably not the best source of information.. For general modules like this perhaps Bootstrap(3/4) might be a more ideal framework if you are open to use one at all.
Edit : MediaQueries
Here's a working solution. Please note that I have commented out some code to demonstrate it in desktop view. Please uncomment that and your code should work in "mobile only" scenario.
document.querySelector('.accordion').addEventListener('click', function (e) {
/*if (screen.width < 768) {*/
var currentTarget = e.target;
if (e.target.classList.contains('accordion-title')) {
var allDesc = Array.prototype.slice.call(document.querySelectorAll('.accordion-description'));
allDesc.forEach(function (el) {
el.classList.add('hidden-xs');
});
e.target.nextElementSibling.classList.remove('hidden-xs');
}
/*}*/
});
/*#media only screen and (max-width: 767px) {
.hidden-xs {
display: none;
}
}*/
/* Comment below code and uncomment above */
/* For demo purpose only */
.hidden-xs {
display: none;
}
.accordion-title,
.accordion-description {
padding: 20px;
margin-bottom: 10px;
}
.accordion-title {
background-color: #ccc;
border-radius: 3px;
border: 1px solid;
}
<div class="accordion">
<div class="accordion-title">Title 1</div>
<div class="accordion-description hidden-xs">Some description</div>
<div class="accordion-title">Title 2</div>
<div class="accordion-description hidden-xs">Some description</div>
</div>

Onload JavaScript sometimes doesn't execute

I have encountered an issue with my JavaScript. Sometimes, the code doesn't execute at all and i can't corelate this to a specific thing, like throwing an error and halting the code or something similar. What i intend to do is to change the picture (a logo) depending of the resolution of the device.
function logo_change() {
if ( document.body.clientWidth < 390 ) {
document.getElementById('logo').style.display = 'none';
document.getElementById('logo-m').style.display = 'block';
}
else {
document.getElementById('logo-m').style.display = 'none';
document.getElementById('logo').style.display = 'block';
}
}
window.onresize = function() {
logo_change();
};
window.onload = function() {
logo_change();
};
#logo {
max-width: 20%;
min-width: 185px;
float: left;
margin-top: 17px;
}
#logo-m {
width: 50px;
float: left;
margin-top: 17px;
display: none;
}
<a id='logo-l' class="logo-l" href="index.php">
<img src="https://d1afx9quaogywf.cloudfront.net/sites/default/files/Logos/facebook-logo_0.png" id='logo' class="logo" name="logo" height="60"></img>
<img src="https://www.ricksdailytips.com/wp-content/uploads/2016/08/f.png" id='logo-m' class="logo-m" height="50"></img>
</a>
I have tried of doing this with media queries doing basically the same thing( with display block and none), but the link would collapse and such.
Also, if i resize the page, the code executes and the logo changes. Thus, i thing is is a window.onload thing.
Thanks for your responses.
To do this with CSS media queries:
#logo, #logo-m {
display: none;
/* other common properties */
}
#media screen and (max-width: 389px) {
#logo-m { display: block; }
}
#media screen and (min-width: 390px) {
#logo { display: block; }
}

Categories