How to make the dropdown menu collapse when not in use - javascript

So I have a dropdown menu and when I click it it works but when I click out it stays open. I've tried using mouseout mousedown onclick ondblclick etc but none of them work. Please help :(
[What I've tried][1]

Attach click listener to your document, if clicked element is img then display dropwdown else hide.
const menu = document.querySelector('#dropdown');
document.addEventListener('click', function(e) {
menu.classList.toggle('show', e.target.tagName == "IMG");
});
.menu {
float: right;
margin: 24px;
position: relative;
display: inline-block;
}
.menu img {
cursor: pointer;
}
.dropdown {
position: absolute;
z-index: 1;
float: right;
width: 150px;
background-color: lightgray;
top: 73px;
right: -24px;
display: none;
}
.dropdown a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {
color: #B00D93;
font-weight: bold;
}
.show {
display: block;
}
<div class="menu" id="menu">
<img src="https://s3.amazonaws.com/media.skillcrush.com/skillcrush/wp-content/uploads/2018/06/Screen-Shot-2018-06-13-at-8.07.34-PM.png" id="dropdownImg" alt="" width="45px" height="45px">
<div class="dropdown" id="dropdown">
Home
About Us
Services
Feedback
</div>
</div>

check this : https://jsfiddle.net/85yz7asd/
showHide = () => {
var dropdown = document.getElementById("dropdown")
dropdown.style.display == "block" ? dropdown.style.display = "none" : dropdown.style.display = "block"
}

This is a Pure HTML and CSS example:
HTML
<div class="dropdown">
<div class="dropdown-btn">Hover Me</div>
<ul class="dropdown-list">
<li>Link #1</li>
<li>Link #2</li>
<li>Link #3</li>
</ul>
</div>
CSS
.dropdown {
display: block;
position: absolute;
}
.dropdown-btn {
text-align: center;
background-color: black;
color: white;
display: block;
position: absolute;
width: 200px;
height: auto;
padding: 10px;
font-size: 16px;
cursor: pointer;
}
.dropdown-list {
position: relative;
display: none;
width: 200px;
height: auto;
list-style: none;
margin-top: 40px;
padding: 0;
}
.dropdown-list li a {
text-align: center;
text-decoration: none;
display: block;
padding: 10px;
width: 200px;
background-color: black;
color: white;
margin-top: 5px;
}
.dropdown-list li a:hover {
background-color: grey;
color: white;
}
.dropdown:hover .dropdown-list {
display: block;
}
working js fiddle

If you want to use your current code, try this.
Clicking on the dropdownImg element will open the menu.
Clicking anywhere else will close the menu.
https://jsfiddle.net/t6wpgjrd/
document.onclick = function(e) {
if(e.target.id === "dropdownImg") {
show();
}
else{
hide();
}
}
And don't forget to remove the onclick and onblur attributes from your dropdownImg element.

Related

How to style & toggle notifications list?

I made a nav bar using nav and li tags, including a notifications icon, I am trying to make notifications nested list to show notifications, and use JavaScript to toggle/hide the menu, so far no luck. I've been looking for snippets online to support my logic, but I am stuck in the styling part and the JavaScript functionality. code below:
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(e) {
if (!e.target.matches('.dropbtn')) {
var myDropdown = document.getElementById("myDropdown");
if (myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
}
html {
scroll-behavior: smooth;
}
* {
font-family: 'Roboto', sans-serif;
font-style: normal;
padding: 0;
margin: 0;
text-decoration: none;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}
::-webkit-scrollbar {
width: 1.32vmin;
}
/*
::-webkit-scrollbar-track{
border: 0.53vmin solid rgba(7, 67, 146, 0.17);
box-shadow: inset 0 0 0.33vmin 0.26vmin rgba(7, 67, 146, 0.17);
}
*/
::-webkit-scrollbar-thumb {
background: #074392;
border-radius: 0vmin;
}
::-webkit-scrollbar-button {
height: 7.45vmin;
background: #074392;
}
body {
font-weight: 400;
font-size: 2.12vmin;
background-color: #FFFFFF;
/*overflow: hidden;*/
height: 100%;
}
h1 {
margin-left: 3vmin;
}
h5 {
margin: 2vmin 3vmin;
position: absolute;
width: 14.72vmin;
font-weight: 500;
font-size: 2.65vmin;
letter-spacing: 0.79vmin;
color: #FFFFFF;
display: inline;
}
nav {
background-color: #074392;
height: 7.42vmin;
width: 100%;
/*position: relative;*/
/*overflow: hidden;*/
position: sticky;
top: 0;
}
img.logo {
margin: 1.855vmin 3vmin;
height: 3.5vmin;
width: 7vmin;
}
nav ul {
float: right;
margin: 1.855vmin 2vmin;
}
nav ul li {
display: inline-block;
}
nav ul li::before {
content: " ";
padding: 0vmin 0.5vmin;
}
nav ul li a {
color: white;
/*margin: 0vmin 1vmin;*/
/*border-top-left-radius: 1.326vmin;
border-top-right-radius: 1.326vmin;
border-bottom-left-radius: 1.326vmin;
border-bottom-right-radius: 1.326vmin;*/
}
a.active,
a:hover {
font-variation-settings: 'FILL' 1;
}
.checkbtn {
color: #ffffff;
float: left;
cursor: pointer;
display: none;
margin: 1.855vmin 3vmin;
}
#check {
display: none;
}
#check:checked~ul {
left: 0;
}
.dropdown {}
.dropdown .dropbtn {
cursor: pointer;
border: none;
outline: none;
background-color: #074392;
color: #FFFFFF;
}
.dropdown:hover .dropbtn,
.dropbtn:focus {
color: #FFFFFF;
font-variation-settings: 'FILL' 1;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #0743922B;
width: 37.5vmin;
overflow-wrap: break-word;
transform: translateX(-56%);
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: justify;
}
.dropdown-content a:hover {
background-color: #0743922B;
}
.show {
display: block;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD#20..48,100..700,0..1,-50..200" />
<div class="container">
<nav>
<input type="checkbox" id="check">
<label for="check" class="checkbtn">
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Menu">menu</i>
</label>
<h5>LOGO</h5>
<ul>
<li>
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Home">home</i>
</li>
<!-- <li> <i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Notifications">notifications</i> -->
<li class="dropdown"><button class="dropbtn" onclick="myFunction()"><i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Notifications">notifications</i></button>
<div class="dropdown-content" id="myDropdown">
<div>Link 1</div>
<div>Link 2</div>
<div>Link asasdasdasdasdasdsadsadasdasdasdasd asddasdas asd asd asd dasd asd</div>
</div>
</li>
<li>
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Tasks">task</i>
</li>
<li>
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Profile">person</i>
</li>
</ul>
<script type="text/javascript" src="JS/ActiveTab.js"></script>
<script type="text/javascript" src="JS/ToggleNotifications.js"></script>
</nav>
<main>
<h1>Example Page</h1>
</main>
</div>
By default set a display: none on the dropdown element and set a display: block on the hover pseudo-class of the dropdown element so when a hover event is triggered the dropdown appears.
Also, you can use classList.toggle method to remove if exists or to add if not exist the class.
Remove
Just add the following to the .css:
#myDropdown {
display: none;
}
#myDropdown.show {
display: block;
}
Remove onclick="myFunction()". And replace the .js with:
const myDropdown = document.getElementById('myDropdown')
addEventListener('click', event => {
let dropbtn = event.target.closest('button.dropbtn')
if (!dropbtn) return myDropdown.classList.remove('show')
console.log('hii')
myDropdown.classList.toggle('show')
})

How to make dropdown menu onclick and close when clicking outside element with Vanilla javascript only?

I'm trying to make dropdown menu onlick and close its menu when clicking outside element.
When i clicked on the News element it doesn't show anything.
I would like it to show when it's clicked and close it's menu when clicking anywhere.
function dropDownMenu() {
var btnNavNews = document.querySelector('.nav__news');
var dropNewSub = document.querySelector('.nav__news__sub');
btnNavNews.addEventListener('click', function () {
dropNewSub.classList.toggle('show');
})
document.addEventListener('click', function (e) {
if (e.target != btnNavNews && e.target.parentNode != dropNewSub) {
dropNewSub.classList.remove('show');
}
})
}
dropDownMenu();
/*Block*/
.nav li {
display: inline-block;
list-style: none;
color: black;
width: 100px;
height: auto;
border: 1px solid red;
font-size: 20px;
text-align: center;
}
/*Element*/
.nav__news__sub {
display: none;
width: 100%;
}
.nav__news__sub__ul {
display: flex;
position: absolute;
width: 70%;
height: 50%;
padding-bottom: 2%;
margin-top: 1%;
padding-right: 2%;
align-items: center;
justify-content: space-evenly;
background-color: grey;
}
.nav__news__sub__ul li {
width: 30%;
height: 50%;
margin-bottom: 10%;
}
.nav__content {
border: solid 1px blue;
margin-top: 50%;
}
.show {
display: block;
}
.nav__item a {
display: block;
}
.nav__item li {
text-align: left;
}
<html>
<head>
<link rel="stylesheet" href="index.css">
<script src="index.js" defer></script>
</head>
<body>
<ul class="nav">
<li Home</li>
<li class="nav__news" News
<div class="nav__news__sub">
<ul class="nav__news__sub__ul">
<li class="img" Example
<div class="nav__content">
<h1>Topic</h1>
</div>
</li>
<li Example2</li>
<li Example3</li>
</ul>
</div>
</li>
</ul>
</body>
</html</html>
Update my code is now works fine, i used wrong variable and change toggle method to remove method
You just used a wrong variable. You should use btnNavNews instead.
Although fixed, I think this logic is still wrong as it will toggle the dropdown if you click anywhere.
function dropDownMenu() {
var btnNavNews = document.querySelector('.nav__news');
var dropNewSub = document.querySelector('.nav__news__sub');
btnNavNews.addEventListener('click', function() {
dropNewSub.classList.toggle('show');
})
document.addEventListener('click', function(e) {
if (e.target != btnNavNews && e.target.parentNode != btnNavNews) {
dropNewSub.classList.toggle('show');
}
})
}
dropDownMenu();
/*Block*/
.nav li {
display: inline-block;
list-style: none;
color: black;
width: 100px;
height: auto;
border: 1px solid red;
font-size: 20px;
text-align: center;
}
/*Element*/
.nav__news__sub {
display: none;
width: 100%;
}
.nav__news__sub__ul {
display: flex;
position: absolute;
width: 70%;
height: 50%;
padding-bottom: 2%;
margin-top: 1%;
padding-right: 2%;
align-items: center;
justify-content: space-evenly;
background-color: grey;
}
.nav__news__sub__ul li {
width: 30%;
height: 50%;
margin-bottom: 10%;
}
.nav__content {
border: solid 1px blue;
margin-top: 50%;
}
.show {
display: block;
}
.nav__item a {
display: block;
}
.nav__item li {
text-align: left;
}
<ul class="nav">
<li Home
</li>
<li class="nav__news" News
<div class="nav__news__sub">
<ul class="nav__news__sub__ul">
<li class="img" Example
<div class="nav__content">
<h1>Topic</h1>
</div>
</li>
<li Example2
</li>
<li Example3
</li>
</ul>
</div>
</li>
</ul>
I suggest you use remove instead so that the dropdown will be hidden when you click anywhere else other than the "News" button:
function dropDownMenu() {
var btnNavNews = document.querySelector('.nav__news');
var dropNewSub = document.querySelector('.nav__news__sub');
btnNavNews.addEventListener('click', function() {
dropNewSub.classList.toggle('show');
})
document.addEventListener('click', function(e) {
if (e.target != btnNavNews && e.target.parentNode != btnNavNews) {
dropNewSub.classList.remove('show');
}
})
}
dropDownMenu();
/*Block*/
.nav li {
display: inline-block;
list-style: none;
color: black;
width: 100px;
height: auto;
border: 1px solid red;
font-size: 20px;
text-align: center;
}
/*Element*/
.nav__news__sub {
display: none;
width: 100%;
}
.nav__news__sub__ul {
display: flex;
position: absolute;
width: 70%;
height: 50%;
padding-bottom: 2%;
margin-top: 1%;
padding-right: 2%;
align-items: center;
justify-content: space-evenly;
background-color: grey;
}
.nav__news__sub__ul li {
width: 30%;
height: 50%;
margin-bottom: 10%;
}
.nav__content {
border: solid 1px blue;
margin-top: 50%;
}
.show {
display: block;
}
.nav__item a {
display: block;
}
.nav__item li {
text-align: left;
}
<ul class="nav">
<li Home
</li>
<li class="nav__news" News
<div class="nav__news__sub">
<ul class="nav__news__sub__ul">
<li class="img" Example
<div class="nav__content">
<h1>Topic</h1>
</div>
</li>
<li Example2
</li>
<li Example3
</li>
</ul>
</div>
</li>
</ul>

Absolute element on the top of relative element hover and on-click problem

I am having a problem with an absolute element. This element is the floating-count which is on the top of the navigation.
Problem is when I hover my mouse on floating-count element, the drop-down arrow also is hovering (it should suppose to hover or change color when the navigation hovers). Then when I am clicking the floating-count element the drop-down navigation also showing (it should suppose to show when the navigation was clicked).
I tried changing (playing with it as I expect to see the solution) and adding z-index to the elements but I am confused with it.
Code here:
$('.mnav').on('click', function() {
if ($(this).children('.dpdown').is(":hidden")) {
console.log('show');
$(this).children('.dpdown').slideDown("fast");
} else {
$(this).children('.dpdown').slideUp("fast");
console.log('hide');
}
});
li.mnav,
.navigation ul.right li.mnav {
display: inline-block;
position: relative;
}
a.text-link,
.navigation ul.right li.mnav a.text-link {
color: #fff;
font-size: 15px;
line-height: 15px;
padding: 14px 24px;
display: block;
text-decoration: none;
text-transform: uppercase;
}
.nav-arrow {
background: yellow;
}
.nav-arrow:after {
top: 40%;
right: 0;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-top-color: #1b6b00;
border-width: 8px;
}
.floating-count {
position: absolute;
z-index: 1;
border-radius: 20px;
background: red;
padding: 4px 8px;
top: -12px;
right: -2px;
text-decoration: none;
color: #FFF;
}
.dpdown {
position: absolute;
left: 0;
top: 50px;
width: 300px;
display: none;
z-index: 1;
}
.dpdown ul li a {
font-size: 12px;
color: #eaf2ac;
padding: 5px 30px;
display: block;
text-decoration: none;
text-transform: uppercase;
}
.dpdown ul {
list-style-type: none;
background-color: #1b6b00;
text-align: left;
margin: 0;
padding: 4px 0;
}
ul.right {
list-style-type: none;
background-color: #208100;
text-align: center;
margin: 0;
padding: 0;
float: left;
border-radius: 5px;
}
ul.right li.mnav:hover,
.navigation ul.right li.mnav a.text-link:hover {
color: #ffea00;
}
.dpdown:hover>.nav-arrow:after {
color: #ffea00;
}
.navigation .mnav:hover>.nav-arrow:after {
border-top-color: #ffea00;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="navigation">
<ul class="right">
<li class="mnav">
Drop Down<span class="nav-arrow"></span>
<span class="floating-count-wrap"><a class="floating-count" href="/#count">2</a></span>
<div class="dpdown">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
</div>
</li>
</ul>
</div>
Try it in jsfiddle:
You have the hover style based on .mnav and the js dropdown triggered by .mnav but .floating-count-wrap is a child of .mnav so it is triggering those events.
I adjusted the css and js to use .mnav .test-link as the selector. I also had to make the css rule use sibling and not parent selection. Similarily, in the js, the selector for the dropdown is no longer a child of $(this) so I updated that to $(this).parent()
updated js fiddle
js
$('.mnav .text-link').on('click', function() { ... });
css
.navigation .mnav .text-link:hover + .nav-arrow:after { ... }

why cannot read property 'top' of undefined?

I have a web page with sticky navbar fixed top and structure of sticky navbar and my sticky navbar structure is
$(function() {
$(window).scroll(function() {
if ($(window).scrollTop() > $(".b").offset().top + $(".b").height() && $("input").val() == "") {
$(".sticky").show();
} else {
$(".sticky").hide();
}
});
});
.container {
width: 1020px;
margin: 0 auto;
}
.container>div {
width: 100%;
height: 300px;
background: #f0f0f0;
border: 1px solid #ccc;
margin: 100px 0;
}
.a:after {
content: "A";
font-size: 250px;
text-align: center;
line-height: 300px;
display: block;
color: #999;
}
.b:after {
content: "B";
font-size: 250px;
text-align: center;
line-height: 300px;
display: block;
color: #999;
}
.c:after {
content: "C";
font-size: 250px;
text-align: center;
line-height: 300px;
display: block;
color: #999;
}
ul.sticky {
list-style-type: none;
padding: 0;
margin: 0;
position: fixed;
top: 0;
left: 0;
width: 100%;
background: #f0f0f0;
height: 50px;
border-bottom: 5px solid #ccc;
display: none;
}
ul.sticky:after,
ul.sticky:before {
content: "";
display: table;
clear: both;
}
ul.sticky li a {
display: block;
float: left;
line-height: 50px;
padding: 0 30px;
text-decoration: none;
color: #999;
}
ul.sticky li a:hover {
background: #999;
color: #f0f0f0;
}
<ul class="sticky">
<li>Home
</li>
<li>About Us
</li>
<li>Download
</li>
<li>Forums
</li>
<li>Contact
</li>
</ul>
<div class="container">
<input type="text" class="input">
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
click to see on codepen
and my question is if I'm not putting my .sticky element another pages javascript notifier give me this error and I am not gonna put my .sticky element every page what do I have to do ?
click to see real demo
click to see getting error
You get this error beacause jQuery did not find the element .hotel-search-box in your website.
Javascript
$(function() {
$(window).scroll(function() {
if (!$(".hotel-search-box").length) {
return false; //Check if the element exist
}
if($(window).scrollTop() > $(".hotel-search-box").offset().top+$(".hotel-search-box").height() && $(".oda-giris-cikis").val() == ""){
$(".sticky-checkin").show();
}else{
$(".sticky-checkin").hide();
}
});
});
To fix your probleme add a .hotel-search-box element in your page where you want to show your sticky menu.

How to hide and open navigation

i want to hide and open the navigation i'v created with the "+" and "-" buttons
- when user will click on the '+' button the navigation will start open one by one.
(notice: the links are on display: none; right now)
fiddle link here: http://jsfiddle.net/RKhRy/5/
The css:
.nav {
height: 600px;
width: 150px;
display: none;
}
.nav li {
width: 150px;
height: 70px;
background-color: #232323;
border-bottom: 1px solid #393939;
text-decoration: none;
list-style: none;
line-height: 70px;
text-align: center;
cursor: pointer;
font-size: 15px;
}
#close {
width: 70px;
height: 70px;
background-color: #737373;
color: #fff;
margin-left: 150px;
position: absolute;
line-height: 70px;
text-align: center;
font-size: 30px;
cursor: pointer;
display: none;
}
#open {
width: 70px;
height: 70px;
background-color: #232323;
color: #fff;
position: absolute;
line-height: 70px;
text-align: center;
font-size: 30px;
cursor: pointer;
}
Try adding this jQuery code:
$("#open").click(function(){
$(".nav, #close").show();
$(".nav li").each(function (i) {
$(this).delay(300*i).animate({width:150},300);
});
$("#open").hide();
});
$("#close").click(function(){
$("#close").hide();
$($(".nav li").get().reverse()).each(function (i) {
$(this).delay(300*i).animate({width:0},300);
});
$("#open").show();
});
The result can be seen in this JSFiddle.
I don't know why i've coded for you but the building blocks of what you're after are here in an updated fiddle: http://jsfiddle.net/RKhRy/12/
Use jQuery's slideToggle();
I've edited your example to make it work: http://jsfiddle.net/g8AF6/3/
new CSS:
body {
color: #fff;
font-family: Tahoma;
font-weight: bold;
position:relative;
}
.nav {
height: 600px;
width: 150px;
display: none;
}
#open:focus{
visibility:hidden;
}
#open:focus + #close + .nav{
display:block;
}
#open:focus + #close {
display:block;
}
.nav li {
width: 150px;
height: 70px;
background-color: #232323;
border-bottom: 1px solid #393939;
text-decoration: none;
list-style: none;
line-height: 70px;
text-align: center;
cursor: pointer;
font-size: 15px;
}
#close {
width: 70px;
height: 70px;
background-color: #737373;
color: #fff;
position: absolute;
top:0;
left:0;
line-height: 70px;
text-align: center;
font-size: 30px;
cursor: pointer;
display: none;
}
#open {
width: 70px;
height: 70px;
background-color: #232323;
color: #fff;
line-height: 70px;
text-align: center;
font-size: 30px;
cursor: pointer;
}
now just add transitions for collapse/expand animation
regards
Basic working fiddle here: http://jsfiddle.net/phdphil/YJ8gf/#base
Essentially this bit of code, plus an id=nav in the right tag:
function setNavVisible(visible) {
var nav = document.getElementById('nav');
var close = document.getElementById('close');
var open = document.getElementById('open');
if(visible) {
nav.style.display = "block";
close.style.display = "block";
open.style.display = "none";
} else {
nav.style.display = "none";
close.style.display = "none";
open.style.display = "block";
}
}
document.getElementById('open').onclick = function() {
setNavVisible(true);
}
document.getElementById('close').onclick = function() {
setNavVisible(false);
}
I've cloned and editted your fiddle. Your html is wrong. You can't have li inside of divs. Thinking of that, your open and close divs can be refactored to something more semanthic. Like this:
Toggle Menu
<ul class="nav">
<li>START HERE</li>
<li>ABOUT</li>
<li>PORTFOLIO</li>
<li>BRANDS</li>
<li>SERVICES</li>
<li>CONTACT</li>
</ul>
I've also added pseudo-elements in css instead of having two elements to only one function.
Check the result here:
http://jsfiddle.net/H7ms7/
You will need to bind keydown event with CSS in my mind.
$(document).keydown(function(e){
if (e.keyCode == *NUMBER) {
}
)};
*The number should be the one that + or - trigger with.
The next thing is with the css, I would just bind $("#element").css('display','block'); With the triggers you want.
If you want them one by one like you said, I'm not absulotly sure but I know it might have to do with CSS3 transition. Check it out, dont want to mislead you.
Goodluck

Categories