ngClass and onClick Not Applying to Div - javascript

I have a javascript project that I'm trying to convert into Angular and I'm having trouble understanding why the classes some of my are making the menu disappear even after reading the documentation again. I want the menu I have to rotate into and X only if .menu-btn is clicked on.
Here is the javascript code I'm trying to convert:
// Select DOM Items
const menuBtn = document.querySelector(".menu-btn");
const menu = document.querySelector(".menu");
const menuNav = document.querySelector(".menu-nav");
const menuBranding = document.querySelector(".menu-branding");
const navItems = document.querySelectorAll(".nav-item");
// Set Initial State Of Menu
let showMenu = false;
menuBtn.addEventListener("click", toggleMenu);
function toggleMenu() {
if (!showMenu) {
menuBtn.classList.add("close");
menu.classList.add("show");
menuNav.classList.add("show");
menuBranding.classList.add("show");
navItems.forEach((item) => item.classList.add("show"));
// Set Menu State
showMenu = true;
} else {
menuBtn.classList.remove("close");
menu.classList.remove("show");
menuNav.classList.remove("show");
menuBranding.classList.remove("show");
navItems.forEach((item) => item.classList.remove("show"));
// Set Menu State
showMenu = false;
}
}
app.component.html
<header>
<div class="container">
<div class="menu-btn" [class.menu-btn.close]="check" (click)="myfunction()">
<div class="btn-line"></div>
<div class="btn-line"></div>
<div class="btn-line"></div>
</div>
<!-- Overlay that comes up when you click menu -->
<!-- Profile Image put in through CSS -->
<nav class="menu" [class.menu-btn.show]="check" (click)="myfunction()">
<div class="menu-branding" [class.menu-btn.show]="check" (click)="myfunction()">
<div class="portrait"></div>
</div>
<!-- Pages -->
<ul class="menu-nav" [class.menu-btn.show]="check" (click)="myfunction()">
<li class="nav-item current" [class.menu-btn.show]="check" (click)="myfunction()">
Home
</li>
<li class="nav-item" [class.menu-btn.show]="check" (click)="myfunction()">
About
</li>
<li class="nav-item" [class.menu-btn.show]="check" (click)="myfunction()">
Work
</li>
<li class="nav-item" [class.menu-btn.show]="check" (click)="myfunction()">
Contact
</li>
</ul>
</nav>
</div>
</header>
app.component.scss
$primary-color: red;
$secondary-color: blue;
#mixin easeOut {
transition: all 0.5s ease-out;
}
.container{
background-color: grey;
height:100px;
box-sizing: border-box;
}
a{
text-decoration: none;
color:white;
}
.btn-line{
color:blue;
}
header{
position: fixed;
z-index:2;
width:100%;
}
.menu-btn{
position: absolute;
z-index:3;
right:35px;
top:35px;
cursor: pointer;
#include easeOut;
.btn-line{
width: 28px;
height: 3px;
margin: 0 0 5px 0;
background: white;
#include easeOut;
}
//Rotate Into X with Menu Lines
&.close {
transform: rotate(180deg);
.btn-line {
// Line 1 - Rotate
&:nth-child(1) {
transform: rotate(45deg) translate(5px, 5px);
}
// Line 2 - Hide
&:nth-child(2) {
opacity: 0;
}
// Line 3 - Rotate
&:nth-child(3) {
transform: rotate(-45deg) translate(7px, -6px);
}
}
}
}
.btn-line{
color:black;
}
app.component.ts
export class AppComponent {
title = 'menu';
check:boolean=true;
myfunction(){
this.check=true;
}
}

I believe the simple answer is that you cannot add two classes at once with the [class.xxx.yyy] directive...
If you want both classes applied you have to do it in two separate [class...] directives, or use an ngClass directive, e.g. [ngClass]="{ xxx: check, yyy: check }"
EDIT (following comment) your template has stuff such as [class.menu-btn.show]="check" I must have guessed wrong when I assumed that you wanted to add both the show and the menu-btn class based on the value of the variable check - if that wasn't your intention, I'm sorry. But at any rate, the class you wish to add must be the sole name in that directive (after class.), so if you want to add the show class, do [class.show]="check". And you can use multiple such directives, each for a different class.

Related

Javascript changes the format of my Div in HTML

I am new to JS, HTML and CSS. I was trying to build a car dealership-like website to practice what I have learned so far and I have come to this one single problem. I made a div that would simulate a user dropdown when triggered using JS method. The method I used is when the user clicked the word car brands list it would show up the hidden div. But what happens is that without JS my dropdown design is all good, but then when JS is inserted into the equation it formats it like how it looks like without any CSS in it. Here is a picture for reference. First one is how it should be, the second one is how it looks with JS in it. Please pardon my bad usage of the tools in stack overflow. I am also new here.
var carListDropdown = document.getElementById("car-brand-dropdown")
carListDropdown.style.display = "none";
function carListDrop(){
if(carListDropdown.style.display === "none"){
carListDropdown.style.display = "block";
} else {
carListDropdown.style.display = "none";
}
}
#car-brand-dropdown {
background: black;
height: 350px;
width: 500px;
color: white;
display: flex;
justify-content: space-around;
margin-right: 90px;
position: absolute;
border-radius: 5px;
margin-top: 2px;
transform: translateX(700px);
z-index: 1;
}
<div class="car-brand-list" onclick="carListDrop()">Car Brands</div>
<div id="car-brand-dropdown">
<ul class="car-brand-list-one">
<li>Aston Martin</li>
<li>Audi</li>
<li>Bentley</li>
<li>BMW</li>
<li>Chevrolet</li>
<li>Dodge</li>
<li>Fiat</li>
<li>Ford</li>
</ul>
<ul class="car-brand-list-two">
<li>Honda</li>
<li>Jaguar</li>
<li>Jeep</li>
<li>KIA</li>
<li>Lamborghini</li>
<li>Land Rover</li>
<li>Lexus</li>
<li>Lotus</li>
</ul>
<ul class="car-brand-list-three">
<li>Mazda</li>
<li>Mercedes-Benz</li>
<li>Mini</li>
<li>Mitsubishi</li>
<li>Nissan</li>
<li>Porsche</li>
<li>Subaru</li>
<li>Toyota</li>
<li>Volkswagen</li>
</ul>
</div>
How it should look like
How it looks with JS inserted into the program
Edit this
var carListDropdown = document.getElementById("car-brand-dropdown")
carListDropdown.style.display = "none";
function carListDrop(){
if(carListDropdown.style.display === "none"){
carListDropdown.style.display = "flex";
} else {
carListDropdown.style.display = "none";
}
}
I removed your entire JS as it is not needed. We can do it directly with the onclick-trigger
I changed the ID of the element to a class for specificty weight reasons.
I added a class (.none) that contains display: none; to hide that element.
I changed the onclick-trigger to document.querySelector('.car-brand-dropdown').classList.toggle('none');
document.querySelector('.car-brand-dropdown') will select your list just like getElementById just the modern statement that can be used to select calsses, ID, tags...
classList.toggle('none) will remove the class .none if the elemnt has this class and add it, if the element does not have this class. So no need for if/else-statments.
.car-brand-dropdown {
background: black;
height: 350px;
width: 500px;
color: white;
display: flex;
justify-content: space-around;
margin-right: 90px;
position: absolute;
border-radius: 5px;
margin-top: 2px;
transform: translateX(700px);
z-index: 1;
}
.none {
display: none;
}
<div class="car-brand-list" onclick="document.querySelector('.car-brand-dropdown').classList.toggle('none');">Car Brands</div>
<div class="car-brand-dropdown none">
<ul class="car-brand-list-one">
<li>Aston Martin</li>
<li>Audi</li>
<li>Bentley</li>
<li>BMW</li>
<li>Chevrolet</li>
<li>Dodge</li>
<li>Fiat</li>
<li>Ford</li>
</ul>
<ul class="car-brand-list-two">
<li>Honda</li>
<li>Jaguar</li>
<li>Jeep</li>
<li>KIA</li>
<li>Lamborghini</li>
<li>Land Rover</li>
<li>Lexus</li>
<li>Lotus</li>
</ul>
<ul class="car-brand-list-three">
<li>Mazda</li>
<li>Mercedes-Benz</li>
<li>Mini</li>
<li>Mitsubishi</li>
<li>Nissan</li>
<li>Porsche</li>
<li>Subaru</li>
<li>Toyota</li>
<li>Volkswagen</li>
</ul>
</div>
The "default" value for a Flex container uses column for direction whereas for your layout you really want to use row. The individual ul elements within the parent container can be left as block level items and the parent will have the flex properties assigned to it. With Javascript you can easily toggle the appearance of an item using classList.toggle ~ which saves using inline node.style.display=... type syntax as you can define the look far easier with CSS.
Rather than adding inline event handlers it is generally considered better practise to use an external event listener -done using addEventListener. This makes for cleaner HTML markup and when the event handlers are stored in an external file it means they can be referenced in other pages by including that script.
/* two utility functions to shorten querySelector calls */
const q=(e,n=document)=>n.querySelector(e);
const qa=(e,n=document)=>n.querySelectorAll(e);
/* find the HTML elements of interest */
const oDiv=q('.car-brand-list');
const oSel=q('#car-brand-dropdown');
/*
add an event handler that toggles the class of the `select` type div,
modifies the class of the clicked text and resets the dataset attribute
that displays the hyperlink text when clicked.
*/
oDiv.addEventListener('click',function(e){
oSel.classList.toggle('flex');
this.classList.toggle('active');
oDiv.dataset.brand='';
});
/*
assign a click handler to each hyperlink - the functionaliyt of the
hyperlinks is unclear but here it is used to display the brand selected.
*/
qa('ul[class^="car-brand"] > li > a').forEach( a=>a.addEventListener('click',function(e){
e.preventDefault();
oDiv.dataset.brand=this.textContent
}));
*{font-family:monospace;}
a{
color:white!important;
text-decoration:none;
}
.car-brand-list{
font-size:1.5rem;
padding:0.25rem;
cursor:pointer;
font-weight:bold;
width:100px;
}
.car-brand-list.active{
background:black;
color:white;
border-radius:0.25rem;
}
.car-brand-list:after{
content:" - "attr(data-brand);
color:gray;
}
[data-brand='']:after{
content:'';
}
#car-brand-dropdown {
background: black;
max-height:350px;
color: white;
display:none;
border-radius:1rem;
transition:ease-in-out all 250ms;
z-index: 1;
}
.car-brand-list,
#car-brand-dropdown{width:500px;}
.flex{
display:flex!important;
justify-content:space-around;
flex-direction:row;
flex-wrap:nowrap;
margin:0.25rem auto;
}
ul{
flex:1;
margin:1rem;
padding:1rem;
list-style:none;
}
ul li{
padding:0.1rem;
font-size:90%;
}
<div class='car-brand-list' data-brand>Car Brands</div>
<div id='car-brand-dropdown'>
<ul class='car-brand-list-one'>
<li><a href='#'>Aston Martin</a></li>
<li><a href='#'>Audi</a></li>
<li><a href='#'>Bentley</a></li>
<li><a href='#'>BMW</a></li>
<li><a href='#'>Chevrolet</a></li>
<li><a href='#'>Dodge</a></li>
<li><a href='#'>Fiat</a></li>
<li><a href='#'>Ford</a></li>
</ul>
<ul class='car-brand-list-two'>
<li><a href='#'>Honda</a></li>
<li><a href='#'>Jaguar</a></li>
<li><a href='#'>Jeep</a></li>
<li><a href='#'>KIA</a></li>
<li><a href='#'>Lamborghini</a></li>
<li><a href='#'>Land Rover</a></li>
<li><a href='#'>Lexus</a></li>
<li><a href='#'>Lotus</a></li>
</ul>
<ul class='car-brand-list-three'>
<li><a href='#'>Mazda</a></li>
<li><a href='#'>Mercedes-Benz</a></li>
<li><a href='#'>Mini</a></li>
<li><a href='#'>Mitsubishi</a></li>
<li><a href='#'>Nissan</a></li>
<li><a href='#'>Porsche</a></li>
<li><a href='#'>Subaru</a></li>
<li><a href='#'>Toyota</a></li>
<li><a href='#'>Volkswagen</a></li>
</ul>
</div>
you'd better use addEventListener, but not html onclick attr.
JS:
document.querySelector('.car-brand-list').addEventListener('click',function(){
carListDrop();
})

How can we close a toggle menu with an outside click

I'm new to coding, I am have a made a decent looking website (https://garibpathshala.in/) with a toggle nav menu for mobiles.
is there any way so that if we click outside the menu it'll close the menu.
Please have a look at my code and help me :)
HTML
<ul class="header-nav-links">
<li class="active">HOME</li>
<li>PROJECTS</li>
<li>TEAM</li>
<li>ABOUT</li>
<li>GALLERY</li>
<li>CONTACT</li>
<li>DONATE</li>
<li>JOIN US</li>
</ul>
<div class="burger">
<div line1></div>
<div line2></div>
<div line3></div>
</div>
JS
const burger = document.querySelector(".burger");
const navLinks = document.querySelector(".header-nav-links");
const links = document.querySelectorAll(".header-nav-links li");
//Toggle Nav
burger.addEventListener("click", () => {
navLinks.classList.toggle("open");
//Animate Links
links.forEach((link, index) => {
if (link.style.animation) {
link.style.animation = ""
}else{
link.style.animation = `navLinkFade 0.5s ease forwards ${index / 7+0.2}s`;
}
});
});
Here is a screenshot of the nav menu
You could remove "open" class from the menu if the event.CurrentTarget is not the hamburger menu and anything else in the document (html or body) is clicked.
You would also need to stopImmediatePropagation on the .hamburger and navLinks itself to stop those from being registered as clicks to the body, since they are children of the body and the event would otherwise bubble up to the body.
MDN reference: https://developer.mozilla.org/en-US/docs/Web/API/Event/bubbles
const burger = document.querySelector(".burger");
const navLinks = document.querySelector(".header-nav-links");
const links = document.querySelectorAll(".header-nav-links li");
const body = document.querySelector('html');
//Toggle Nav
burger.addEventListener("click", (e) => {
navLinks.classList.toggle("open");
e.stopImmediatePropagation();
//Animate Links
links.forEach((link, index) => {
if (link.style.animation) {
link.style.animation = "";
}else{
link.style.animation = `navLinkFade 0.5s ease forwards ${index / 7+0.2}s`;
}
});
});
navLinks.addEventListener("click", (eve) => {
eve.stopImmediatePropagation();
});
body.addEventListener("click", (ev) => {
if (ev.currentTarget != burger) {
navLinks.classList.remove("open");
}
});
.burger {
display: block;
cursor:pointer;
}
.header-nav-links {
display: block;
}
.header-nav-links.open {
transform: translateX(0%);
}
.header-nav-links {
right: 0;
position: fixed;
height: 92vh;
top: 16vh;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
align-items: center;
width: 50%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.header-nav-links li {
list-style-type: none;
}
.header-nav-links li:hover {
border: 1px solid #fff;
border-radius: 6pc;
background-color: #007bff;
}
.header-nav-links a {
color: whitesmoke;
text-decoration: none;
font-family: Arial, sans-serif;
font-weight: normal;
font-size: 16px;
border: 0px solid white;
transition: 400ms;
padding: 5px 15px;
border-radius: 19px;
}
<ul class="header-nav-links">
<li class="active">HOME</li>
<li>PROJECTS</li>
<li>TEAM</li>
<li>ABOUT</li>
<li>GALLERY</li>
<li>CONTACT</li>
<li>DONATE</li>
<li>JOIN US</li>
</ul>
<div class="burger">
BURGER
<div line1></div>
<div line2></div>
<div line3></div>
</div>
You could add a click listener on body or document and rely on event delegation to take the appropriate action, as in the sample code below.
(See the in-code comments for further clarification.)
// Selects some DOM elements and converts the collection to an array
const listItems = Array.from(document.querySelectorAll(".header-nav-links > li"));
// Calls `handleMenuDisplay` when anything is clicked
document.addEventListener("click", handleMenuDisplay);
// Defines `handleMenuDisplay`
function handleMenuDisplay(event){ // Listeners can access their triggering events
const clickedThing = event.target; // The event's `target` property is useful
// Depending on what was clicked, takes an appropriate action
if(listItems.includes(clickedThing)){ // Arrays have an `includes` method
openMenu(clickedThing);
}
else{
closeMenu();
}
}
function openMenu(clickedLi){
demo.textContent = clickedLi.dataset.demoText;
}
function closeMenu(){
demo.textContent = "Menu is closed";
}
li{ margin: 7px; padding: 3px; border: 1px solid grey; }
#demo{ margin-left: 2ch; font-size: 1.5em; font-weight: bold; }
<ul class="header-nav-links">
<li data-demo-text="Home menu is open">HOME</li>
<li data-demo-text="Projects menu is open">PROJECTS</li>
<li data-demo-text="Team menu is open">TEAM</li>
<li data-demo-text="About menu is open">ABOUT</li>
</ul>
<p id="demo">Menu is closed</p>
Note: My use of custom data-attributes was just to make the sample code a bit cleaner -- it's not part of event delegation, and the display text for each li could just have easily been written out manually in the script.
Based on the other solutions:
An even simpler way is to use the focus and blur states of DOM elements to handle the state for your menu.
document.querySelectorAll('.menu').forEach((menu) => {
const items = menu.querySelector('.menu-items');
menu.addEventListener('click', (e) => {
items.classList.remove("hide");
menu.focus(); // Probably redundant but just in case!
});
menu.addEventListener('blur', () => {
items.classList.add("hide");
});
});
.menu {
cursor: pointer;
display: inline-block;
}
.menu > span {
user-select: none;
}
.menu:focus {
outline: none;
border: none;
}
.hide {
display: none;
}
.menu-items > * {
user-select: none;
}
<div class="menu" tabindex="0">
<span>Menu +</span>
<div class="menu-items hide">
<div>Item 0</div>
<div>Item 1</div>
<div>Item 2</div>
</div>
</div>
The secret here is to give the .menu div a tabindex so that it's focusable by the browser.
First things first for the JS:
Search the page for any instance of the menu class document.querySelectorAll
Get the items element that's currently hidden by .hide
When somebody clicks on the menu remove the .hide class from the items
This should focus the div, but just in case menu.focus is called!
Then whenever somebody loses focus of the div, AKA clicks away etc. Add the .hide class back.
This could be expanded to change the text of the button, do all sorts of other things. It also keeps your code super clean because you're relying on the browsers own internal state management, so you don't have to do any checks.
Handle a second click close
Right so it works great, but in order to make it function as most people expect UI we need to close it when the menu div is clicked again too (replace span with any class you need):
...
menu.querySelector('span').addEventListener('click', (e) => {
e.stopPropagation();
menu.blur();
});
menu.addEventListener('click', (e) => {
items.classList.remove("hide");
menu.focus(); // Probably redundant but just in case!
});
menu.addEventListener('blur', () => {
items.classList.add("hide");
});
...

Can`t change the height on a image in javascript

I want to create a function for for my header when its changing his size.
I have a logo img inside the header.I want when i change the headers height to be for example 80px the image to be 80 px as well.
I initialized a function in Javascript but doesnt work( i`m a beginner at Javascript). Please tell me what i m doing wrong in js and maybe show me the right way to do it.
<header class="header">
<div class="container">
<div class="header-content">
<img src='http://www.lazarangelov.com/wp-content/uploads/2015/12/logo1.jpg' class="logo" alt="logo">
<div class="menu-links">
<ul class="links-list">
<li>Home</li>
<li>Bio</li>
<li>Training</li>
<li>Academy</li>
<li>Gallery</li>
<li>Store</li>
<li>Contacts</li>
</ul>
</div>
</div>
</div>
</header>
.header {
background: blue;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 20;
height: 80px;}
.header-content{
display:flex;
}
.menu-links{
display:flex;
}
.links-list{
display:flex;
color:white;
}
const mainNav = document.querySelector('.header');
const img = document.querySelector('.logo');
if (mainNav.style.height == '80px') {
img.style.height = '80px';
} else {
img.style.height = '100px';
}
The .style property can only return style information that has been set directly into the HTML element, either statically in the HTML as in: <p style="something here"> or via the .style being set in JavaScript as in: element.style = something;. Your code is based on an if condition that checks mainNav.style.height, but the style property hasn't been set in HTML or JavaScript at that point.
Instead, use .getComputedStyle(), which returns the final value for the provided style after all computations (regardless of where they were applied) are taken into account.
I've added a red border to your image in the code below to show that it is expanding the height to be the same size as the header.
const mainNav = document.querySelector('.header');
const img = document.querySelector('.logo');
// You can't check the .style property if the element
// hasn't had that attribute or property set yet.
if (getComputedStyle(mainNav).height == '80px') {
img.style.height = '80px';
} else {
img.style.height = '100px';
}
.logo { border:1px dashed red; }
.header {
background: blue;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 20;
height: 80px;}
.header-content{
display:flex;
}
.menu-links{
display:flex;
}
.links-list {
display:flex;
color:white;
}
.links-list a { color: white; }
<header class="header">
<div class="container">
<div class="header-content">
<img src=
'http://www.lazarangelov.com/wp-content/uploads/2015/12/logo1.jpg'
class="logo" alt="logo">
<div class="menu-links">
<ul class="links-list">
<li>Home</li>
<li>Bio</li>
<li>Training</li>
<li>Academy</li>
<li>Gallery</li>
<li>Store</li>
<li>Contacts</li>
</ul>
</div>
</div>
</div>
</header>
The style property in Javascript only gives you the element's inline styles - those defined directly in a style attribute on it.
You need getComputedStyle to access the actual properties used, taking into account all CSS rules.

Dropdown Menu using javascript, HTML and CSS

I can't seem to get this to work. I don't wanna put jQuery in yet. Just doing plain javascript. When I click on the image nothing happens. I need it to dropdown the navigation when I click the image. Edited my Javascript code. I added alert to show the current status of what class the toggle is using. But still I cant get to change it from header_navigation_mobile to header_navigation_mobile.is_open
This is my HTML CODE for the Clickable Image
<a href="#" onclick="toggleMenu()">
<img class="mobile_navigation_button" src="{{site.baseurl}}/assets/img/menu.svg"/>
</a>
This is the HTML for the drop down navigation
<div class="header_navigation_mobile">
<ul>
<li>HOME</li>
<li>ABOUT</li>
<li>CONTACT</li>
<li> </li>
<li> </li>
</ul>
</div>
Then my CSS For the Clickable Image to show the navigation
.header_navigation_mobile.is_open{
display: block;
transform: translateY(0%);
}
This is the CSS for the Clickable Image first state which is to Hide it
.header_navigation_mobile{
display: none;
position: absolute;
width: 290px;
background: #484547;
transform: translateY(-100%);
transition: all 0.3s ease-in-out;
}
Then finally my Javascript
function toggleMenu(){
var mobileNav = document.getElementById('mobile_Nav');
var mobileNav_toggle = mobileNav.getAttribute("class");
if(mobileNav_toggle == "header_navigation_mobile") {
mobileNav_toggle == "header_navigation_mobile.is_open";
}
else {
mobileNav_toggle == "header_navigation_mobile";
}
alert(mobileNav_toggle);
}
I would give the menu an ID so it's easier to target, then just toggle a class that you use to hide/show the menu.
.header_navigation_mobile {
display: none;
}
.open {
display: block;
}
toggle
<div class="header_navigation_mobile" id="mobilenav">
<ul>
<li>HOME</li>
<li>ABOUT</li>
<li>CONTACT</li>
<li>
</li>
<li>
</li>
</ul>
</div>
<script>
function toggleMenu(){
var nav = document.getElementById('mobilenav');
nav.classList.toggle('open');
}
</script>
In your JS try like this.use querySelector for selecting elements.And for setting and getting css properties use selector.style.property_name.
function toggleMenu(){
var mobileNav_Hide = document.querySelector('.header_navigation_mobile');
var mobileNav_Show = document.querySelector('.header_navigation_mobile.is_open')
if(mobileNav_Hide.style.display == "none"){
mobileNav_Show.stylr.display == "block";
}
else{
mobileNav.style.display = "none";
}
}
I know this is not a specific answer to your question but may be a handy solution as well. I put together a jsfiddle of a hidden menu you can easily edit to your needs. Here is the link.
#Btn{
position: fixed;
right: 20px;
width: 20px;
height: 24px;
background: linear-gradient(#FFF,#DDD);
border: #AAA 1px solid;
border-radius: 2px;
padding: 2px 5px;
cursor: pointer;
transition: border 0.3s linear 0s;
}
#Btn:hover{
border: #06F 1px solid;
}
#Btn:hover div{
background: #06F;
}
#Btn > div{
width: 20px;
height: 4px;
background: #333;
margin: 3px 0px;
border-radius: 4px;
transition: background 0.3s linear 0s;
}
#hidden{
position: fixed;
right: -300px;
top: 60px;
width: 260px;
height: 0px;
background: #333;
color:#ededed;
padding:15px;
transition: right 0.3s linear 0s;
}
<script>
function toggleBTN(){
var hidden = document.getElementById("hidden");
hidden.style.height = window.innerHeight - 60+"px";
if(hidden.style.right == "0px"){
hidden.style.right = "-300px";
} else {
hidden.style.right = "0px";
}
}
</script>
<div id="Btn" onclick="toggleBTN()">
<div></div>
<div></div>
<div></div>
</div>
<div id="hidden">
<ul>
<li>MENU ITEM 1</li>
<li>MENU ITEM 2</li>
<li>MENU ITEM 3</li>
</ul>
</div>
<div id="page_content">
<script>
for(var i = 0; i < 10; i++){ document.write("<h2>"+(i+1)+". Dummy page content ... </h2>"); }
</script>
</div>
Hope this helps :)
There are a few things in the else statement where is mobileNav coming from there is no instance of that anywhere in your code. Taking a step back a minute from your solution does the adding and removal of the classname is_open define the entire show hide behaviour you desire?
Your process of getting the same element with the subclass present/not present and then trying to set the display property is confusing.
You have an equality comparer when setting the display property when it should be just a single equals which along with my first statement i think is your main problem.
Instead of the way you are doing it i would just look at toggling the is_open class this link Toggle class on HTML element without jQuery shows how to do that and also demonstrates a few other ways of toggling styles including without javascript
Finally just check because im being lazy that display is valid as a property and that it shouldnt instead be style.display as others have indicated
js
let c = document.getElementById("dropdownlist");
let e = document.getElementById("dropdownicon");
let d = e.classList.toggle('fa-angle-down');
if(d===true) {
if(c.style.display==='none'){
c.style.display = 'block';
}
else{
c.style.display ='block';
}
}
else{
c.style.display = 'none';
}

Replace main navigation links with submenu links on hover - instead of a dropdown

I recently saw a navigation effect I liked on a website, but can't find it to check the code and see how it was done. There was a standard menu bar that was 100% width and aprox 30px in height, with each link equally spaced within it. When you hovered on the gallery link the whole menu bar changed and the links were replaced with the submenu. No dropdown, the whole menu bar was changed to the submenu items. I can't quite sort out how this was done. Any suggestions would be appreciated. Here is the example html markup I am working with:
<nav>
<ul class ="menu">
<li class ="nav__item">about</li>
<li class ="nav__item">galleries
<ul class="submenu">
<li class ="nav__subitem">one</li>
<li class ="nav__subitem">two</li>
<li class ="nav__subitem">three</li>
<li class ="nav__subitem">four</li>
<li class ="nav__subitem">five</li>
<li class ="nav__subitem">six</li>
</ul> <!-- close sub -->
</li>
<li class ="nav__item">stories</li>
<li class ="nav__item">contact</li>
<li class ="nav__item">thank you</li>
</ul>
</nav>
Not sure if this is what you are looking for but check out this fiddle
Setting a fixed height to the navigation with relative positioning and targeting the parent of the nested ul on mouse over I was able to achieve this effect.
nav {
height: 50px;
overflow: hidden;
position: relative;
background: #999999;
}
.menu {
list-style-type:none;
position: relative;
}
ul {
padding: 0;
margin: 0;
}
li.nav__item {
float:left;
}
li.nav__item a {
padding: 0 15px;
line-height:50px;
}
.submenu {
position:absolute;
left:15px;
}
.nav__subitem {
line-height: 50px;
float: left;
list-style: outside none none;
}
And the little bit of jQuery magic to tie it all together.
$(".has-children").mouseover(function () {
$(".menu").css("top", "-50px");
});
$(".main-navigation").mouseleave(function () {
$(".menu").css("top", "0px");
});

Categories

Resources