Sidebar navigation toggle with single button - javascript

I have implemented the following sidebar navigation into a simple admin. I've got it working and moved to the right side. I would like to have it appear and disappear using a single button rather than a separate close and open button. I tried modifying the JS with an onToggle function that if isOpen was null, it would open the panel and then set isOpen to true and then the next time it ran, it would delete isOpen. I'm very new at JS and this failed so I thought I'd ask here. How do I get this puppy appearing and disappearing with a single button?
http://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_sidenav
Thank you kindly.

<!DOCTYPE html>
<html>
<style>
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 60px;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s
}
.sidenav a:hover, .offcanvas a:focus{
color: #f1f1f1;
}
.closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px !important;
margin-left: 50px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
</style>
<body>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<h2>Animated Sidenav Example</h2>
<p>Click on the element below to open the side navigation menu.</p>
<script>
function openNav() {
var e = document.getElementById("mySidenav");
if (e.style.width == '250px')
{
e.style.width = '0px';
}
else
{
e.style.width = '250px';
}
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
</script>
</body>
</html>
This is the same code with little modifications in the openNav() method. For triggering the sideNavbar with a button, it needs to be visible before and after triggering the sideNavBar. So i have moved the view button to the top and i have modified the top property of sidenav to keep the trigger button visible even after activation
You can view this in action here: https://jsfiddle.net/ngohrvk1/

I know the question is tagged with JavaScript and you probably don't want to change the markup or add new elements. But if you could, here's a pure CSS solution that works.
body {
margin: 0;
}
.sidebar-toggle {
position: absolute;
left: 0;
top: 0;
z-index: 2;
padding: 10px;
background: red;
color: white;
}
#sidebar-toggle-input {
display: none;
}
#sidebar-toggle-input+label:before {
content: "➡️";
}
#sidebar-toggle-input:checked + label:before {
content: "❌"
}
.sidebar {
position: fixed;
width: 200px;
transition: 0.3s;
background: blue;
height: 100vh;
top: 0;
left: 0;
transform: translateX(-100%);
}
#sidebar-toggle-input:checked ~ .sidebar {
transform: none;
}
<input type="checkbox" id="sidebar-toggle-input" />
<label class="sidebar-toggle" for="sidebar-toggle-input"></label>
<div class="sidebar"></div>

This code will help you out, I have created a function and saving data-isshown attribute on the element, to get whether the element is shown or not, we can decide this on the basis of the width as well but this is more generic approach
function toggleNav() {
var element = document.getElementById("mySidenav")
var shown = element.getAttribute("data-isshown");
if (shown == "true") {
element.setAttribute("data-isshown", "false");
element.style.width = "0";
} else {
element.setAttribute("data-isshown", "true");
element.style.width = "250px";
}
}
Whole code would look like this
function toggleNav() {
var element = document.getElementById("mySidenav")
var shown = element.getAttribute("data-isshown");
if (shown == "true") {
element.setAttribute("data-isshown", "false");
element.style.width = "0";
} else {
element.setAttribute("data-isshown", "true");
element.style.width = "250px";
}
}
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s
}
.sidenav a:hover,
.offcanvas a:focus {
color: #f1f1f1;
}
.closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px !important;
margin-left: 50px;
}
#media screen and (max-height: 450px) {
.sidenav {
padding-top: 15px;
}
.sidenav a {
font-size: 18px;
}
}
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<h2>Animated Sidenav Example</h2>
<p>Click on the element below to open the side navigation menu.</p>
<span style="font-size:30px;cursor:pointer" onclick="toggleNav()">☰ open</span>

Related

why doesn't off canvas code work in mobile?

I got this code from https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_sidenav and it works fine in mobile as is. So simple, yet effective. But my usage doesn't work in my mobile or my customer's mobile.
console says:
(index):66 Uncaught TypeError: Cannot read properties of null (reading 'style')
at openNav ((index):66)
at HTMLDivElement.onmouseover ((index):79)
Would anyone like to hazard a guess as to why this doesn't work?
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #96AD74;
background-color: #9C836E;
overflow-x: hidden;
transition: 0.5s;
padding-top: 30px;
letter-spacing: 1px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #E2FAC0;
display: block;
transition: 0.3s;
text-shadow: 1px 1px 0 #000;
}
.sidenav a:hover {
color: darkblue;
background: #808000;
background: #7E6EB5;
background: #FFAC1C;
text-shadow: none;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
text-shadow: none;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {
padding-top: 15px;
}
.sidenav a {
font-size: 18px;
}
<div id="mySidenav" class="sidenav" onmouseleave="closeNav();">
<div class="pcc">MENU</div>
home
coaching
biography
contact
</div>
If I understand correctly, you want to close the menu when the user touches anything outside of it on a phone.
Add the following to your JavaScript file:
document.addEventListener('click', function(e) {
var mySidenav = document.getElementById("mySidenav");
var openButton = document.getElementById("openButton");
if (mySidenav.style.width == "250px" && !mySidenav.contains(e.target) && e.target != openButton) {
closeNav();
}
});
This will make it so when you click (touch) on any element besides the open button, it will close the sidebar.
Also, don't forget to set the ID of the element opening the navbar to "openButton", for example in the W3School tutorial you linked, you should modify it like this:
<span id="openButton" style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>

How can I close menu after click outside menu?

I want to make hiding sidebar menu which will be opened whenuser click button. After that when user click outside menu - menu will be closed. How can I make this function in this case?
JsFiddle
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidenav a:hover {
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
You can react on a click on the entire document element and find out whether the target is located within your menu:
document.documentElement.addEventListener("click", function(e){
if (e.button != 1) // left mouse
return; // anything else => do nothing
var target = e.target;
var navItem = document.getElementById("mySidenav");
do{
if (target == navItem)
return; // clicked within "mySidenav" => do nothing
target = target.parentNode;
}
while(target != null);
// react here
closeNav(); // must be implemented somewhere
});
It is desirable not to react at all if you detect that the click was indeed fired within your menu because otherwise you might close the menu before the click gets bubbled to the item => no menu item click detected.
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
}
document.addEventListener('mousedown',function(event){
var side_dom = document.getElementById("mySidenav")
if(side_dom.style.width == '250px'){
if(!side_dom.contains(event.target)){
document.getElementById("mySidenav").style.width = "0";
}
}
})
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidenav a:hover {
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
<body>
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</s
</body>

Cannot fully scroll down in side panel in an html example from w3school

I created an example:
jsfiffle
exactly identical to this one in w3schools:
w3schools sidenav_push
except that mine has more anchor tags in the side panel.
Why scrolling to the very bottom of the left pane is not possible?
At some point I saw a difference in that behavior when you scroll down using the bar or with the mouse wheel, so please try both. i tried in Chrome and Firefox.
Html:
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
<a>A</a>
<a>B</a>
<a>C</a>
<a>D</a>
<a>E</a>
<a>F</a>
<a>G</a>
<a>H</a>
<a>I</a>
<a>J</a>
<a>K</a>
<a>L</a>
<a>M</a>
<a>N</a>
<a>O</a>
<a>P</a>
<a>Q</a>
<a>R</a>
<a>S</a>
<a>T</a>
<a>U</a>
<a>V</a>
<a>..</a>
<a>W</a>
<a>X</a>
<a>Y</a>
<a>Z</a>
</div>
<div id="main">
<h2>Sidenav Push Example</h2>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
</div>
<script>
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
document.getElementById("main").style.marginLeft = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
</script>
</body>
CSS:
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s;
}
.sidenav a:hover, .offcanvas a:focus{
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
The main issue is that the padding-top property pushes the content down, but overflow only limits to height.
If you want to the padding to compute with the 100% height, you have to modify the box-sizing.
.sidenav {
box-sizing: border-box;
}
Answer based on: CSS padding overrides overflow?
Working JSFiddle: https://jsfiddle.net/wcfwLxtx/2/
Add this to your CSS.
.sideNav {
overflow: auto;
}
That should do it.
The issue is related to the padding-top. Eliminating it will enable the entire content to be displayed.
Here's an example https://jsfiddle.net/kzpjmmf2/
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
}
you just need to reduce the padding
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 10px;
}
here is a working example
https://codepen.io/anon/pen/EXXaKN

Issues translating Left Oriented Off-Screen Navbar to the Right of the Screen

I'm trying to adapt the "How To - Side Navigation" from w3schools.com to appear from the right side of the screen, but am having difficulty. The example from w3schools is provided below, as well as my attempt.
I've found with my attempt, the 'x' for the exit button is persistent
on the webpage (but is still functional) & the height of the navbar is
only the height of the unordered list.
The Sidenav Push Example (Left):
<!DOCTYPE html>
<html>
<style>
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s
}
.sidenav a:hover, .offcanvas a:focus{
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
</style>
<body>
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<div id="main">
<h2>Sidenav Push Example</h2>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
</div>
<script>
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
document.getElementById("main").style.marginLeft = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
</script>
</body>
</html>
My Attempt:
<!DOCTYPE html>
<html>
<style>
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: inherit;
z-index: 1;
top: 0;
left: 0;
float: right;
background-color: #4D394B;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.0s
}
.sidenav a:hover, .offcanvas a:focus{
color: #f1f1f1;
}
.sidenav .closebtn {
float: left;
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
</style>
<body>
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<div id="main">
<h2>Sidenav Push Example</h2>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
</div>
<script>
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
document.getElementById("main").style.marginLeft = "-250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
</script>
</body>
</html>
What can I do to change the Sidenav Push Example to come from the right of the screen?
Like this, where you change left: 0; in .sidenav to right: 0; and in the script you change style.marginLeft to style.marginRight (note this occur in 2 places)
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
document.getElementById("main").style.marginRight = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginRight = "0";
}
body {
font-family: "Lato", sans-serif;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
right: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s
}
.sidenav a:hover,
.offcanvas a:focus {
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {
padding-top: 15px;
}
.sidenav a {
font-size: 18px;
}
}
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<div id="main">
<h2>Sidenav Push Example</h2>
<p>Click on the element below to open the side navigation menu, and push this content to the left.</p>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
</div>

javascript priority inside a function

I am trying to get overlay opened first than the alert box to be opened after it. Alert box comes first even if i have written it after the overlay one.So i need to know what problem is here in my code
<!DOCTYPE html>
<html>
<style>
body {
margin: 0;
font-family: 'Lato', sans-serif;
}
.overlay {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.9);
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 25%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #818181;
display: block;
transition: 0.3s;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 45px;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay a {font-size: 20px}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
</style>
<body>
<div id="myNav" class="overlay">
×
<div class="overlay-content">
</div>
</div>
<h2>Fullscreen Overlay Nav Example</h2>
<p>Click on the element below to open the fullscreen overlay navigation menu.</p>
<p>In this example, the navigation menu will slide in, from left to right:</p>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
<script>
function openNav() {
document.getElementById("myNav").style.width = "100%";
alert("hello");
}
function closeNav() {
document.getElementById("myNav").style.width = "0%";
}
</script>
</body>
</html>
Your javascript code is not going to wait at your
document.getElementById("myNav").style.width = "100%";
line while the css transition happens. It is going to immediately start executing whatever lines of javascript come next.
If you want an action to happen after a transition you need to add an event listener for transitionend (or animationend if using keyframe animations).
So if you want your alert to happen after your transition you need to change your code to something like
var nav = document.getElementById("myNav");
nav.addEventListener("transitionend",function(){
//this callback is called when transition ends
alert("hello");
});
nav.style.width = "100%";
Demo
var nav = document.getElementById("myNav");
var btn = document.querySelector("button");
function openNav() {
nav.addEventListener("transitionend", function() {
//this callback is called when transition ends
alert("hello");
});
nav.style.width = "100%";
}
btn.addEventListener("click", openNav);
#myNav {
display: block;
width: 0%;
height: 100px;
background: grey;
transition: width 1s;
}
<div id="myNav">
</div>
<button>Open</button>

Categories

Resources