Change which image is displayed on hover and click - javascript

I'm not a developer. I've been however tasked with coming up with a solution for a small project at work with jQuery and I have no clue where to begin. Here's my codepen: https://codepen.io/axo1/pen/mdBLRjL
What I need to is this (all graphics and texts are placeholders):
What I managed to achieve
Image item1 is supposed to be the first visible,
Hovering on the buttons below the graphic changes which image is displayed,
What I don't know how to achieve
The buttons below should be clickable. Clicking on a button changes the "active" graphic above. For example: if I click on the Second item button, the item2 image will be displayed even after I unhover the button, and so forth.
Any tips of what I should look into?
Unfortunately jQuery is heavily preferred here.
$(document).on({
mouseenter: function() {
$(".item1").toggleClass("active hidden");
$(".item2").toggleClass("hidden");
},
mouseleave: function() {
$(".item1").toggleClass("active hidden");
$(".item2").toggleClass("hidden");
}
}, ".item2btn");
$(document).on({
mouseenter: function() {
$(".item1").toggleClass("active hidden");
$(".item3").toggleClass("hidden");
},
mouseleave: function() {
$(".item1").toggleClass("active hidden");
$(".item3").toggleClass("hidden");
}
}, ".item3btn");
img {
max-width: 15%;
position: absolute;
top: 0;
left: 0;
}
.hidden {
visibility: hidden;
}
.active {
visibility: visible;
}
#container {
display: flex;
justify-content: flex-start;
align-items: center;
color: white;
position: absolute;
top: 250px;
}
#container ul {
padding: 1em;
}
#container ul>li {
background: black;
margin: 1em;
padding: 1em;
list-style-type: none;
display: inline;
}
#container ul>li:hover {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<img src="https://www.models-resource.com/resources/big_icons/13/12406.png" class="active items item1">
<img src="https://banner2.cleanpng.com/20180410/rce/kisspng-the-legend-of-zelda-majora-s-mask-hyrule-warriors-the-legend-of-zelda-5acc7b7a4870f6.4303262815233503942967.jpg" class="hidden items item2">
<img src="https://i.pinimg.com/originals/4a/a5/df/4aa5df83115df6c96732a2d76ccb4f1b.jpg" class="hidden items item3">
<div id="container">
<ul>
<li class="item1btn">First item</li>
<li class="item2btn">Second item</li>
<li class="item3btn">Third item</li>
</ul>
</div>

Here is a working version
I kept your style - I think it can be shortened to be more DRY
const $images = $(".items")
let $currentItem = $(".items").eq(0)
$("#container li").on({
"click": function() {
const id = $(this).data("id").replace("btn", "");
$images
.removeClass("active")
.addClass("hidden")
$currentItem = $(`.${id}`)
.removeClass("hidden")
.addClass("active");
},
"mouseover": function() {
const id = $(this).data("id").replace("btn", "");
$images
.removeClass("active")
.addClass("hidden")
$(`.${id}`)
.removeClass("hidden")
.addClass("active");
},
"mouseout": function() {
$images
.removeClass("active")
.addClass("hidden")
$currentItem
.removeClass("hidden")
.addClass("active");
}
})
img {
max-width: 15%;
position: absolute;
top: 0;
left: 0;
}
.hidden {
visibility: hidden;
}
.active {
visibility: visible;
}
#container {
display: flex;
justify-content: flex-start;
align-items: center;
color: white;
position: absolute;
top: 250px;
}
#container ul {
padding: 1em;
}
#container ul>li {
background: black;
margin: 1em;
padding: 1em;
list-style-type: none;
display: inline;
}
#container ul>li:hover {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<img src="https://www.models-resource.com/resources/big_icons/13/12406.png" class="active items item1">
<img src="https://banner2.cleanpng.com/20180410/rce/kisspng-the-legend-of-zelda-majora-s-mask-hyrule-warriors-the-legend-of-zelda-5acc7b7a4870f6.4303262815233503942967.jpg" class="hidden items item2">
<img src="https://i.pinimg.com/originals/4a/a5/df/4aa5df83115df6c96732a2d76ccb4f1b.jpg" class="hidden items item3">
<div id="container">
<ul>
<li data-id="item1">First item</li>
<li data-id="item2">Second item</li>
<li data-id="item3">Third item</li>
</ul>
</div>

Related

How to load a new image on click?

I have a <div> tag which contains an <ul> with three <li>s with an <a> in each of them.
I have another <div> tag which contains one default image.
$(document).ready(function() {
$(".vas").click(function() {
$("#banner div").hide();
$("#vas").show();
});
$(".anb").click(function() {
$("#banner div").hide();
$("#anb").show();
});
$(".tam").click(function() {
$("#banner div").hide();
$("#tam").show();
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="header">
<img src="../images/nagam1.png">
<ul>
<li>Vasantha</li>
<li>Anbalagan</li>
<li>Tamilmani</li>
</ul>
</div>
<div id="banner">
<img src="../images/family.jpg">
</div>
When clicking every link, how can I make the corresponding image load in <div id="banner">, i.e. hiding the last image and loading the new corresponding image in it?
You could do something like this:
$(document).ready(function () {
$('.nav-img-click').on('click', function(event){
event.preventDefault();
// on click hide all data-js-images inside #banner div
$('#banner [data-js-img]').hide();
// show the one which maches the "name"
$('#banner img[data-js-img="' + $(this).attr('name') + '"').show();
});
})
[data-js-img] {
display: none; /* hide all images which have data-js-img */
}
[data-js-img="default"] {
display: inline-block; /* but show the data-js-img=DEFAULT */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="header">
<img src="https://picsum.photos/200/30">
<ul>
<li>Vasantha</li>
<li>Anbalagan</li>
<li>Tamilmani</li>
</ul>
</div>
<div id="banner">
<img data-js-img="default" src="https://picsum.photos/200">
<img data-js-img="tam" src="https://loremflickr.com/320/240/dog">
<img data-js-img="anb" src="https://loremflickr.com/g/320/240/paris">
<img data-js-img="vas" src="https://loremflickr.com/320/240/brazil,rio">
</div>
Html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="header">
<div class="logo">LOGO</div>
<ul class="nav">
<li>Vasantha</li>
<li>Anbalagan</li>
<li>Tamilmani</li>
</ul>
</div>
<div id="banner">
<img class="banner-img" src="https://images.pexels.com/photos/4098987/pexels-photo-4098987.jpeg?cs=srgb&dl=pexels-taryn-elliott-4098987.jpg&fm=jpg">
</div>
Css
ul,
li {
list-style: none;
}
a {
text-decoration: none;
}
#header {
display: flex;
align-items: center;
height: 40px;
}
#header .logo {
width: 100px;
height: 100%;
text-align: center;
line-height: 40px;
background: pink;
}
#header .nav {
display: flex;
height: 100%;
justify-content: center;
}
.nav li {
width: 100px;
height: 100%;
text-align: center;
line-height: 40px;
}
.nav a {
color: #000;
}
.nav a:hover {
color: #ccc;
}
.banner-img {
width: 1000px;
}
Javascript
$(document).ready(function () {
const imgUrls = {
vas:
"https://images.pexels.com/photos/1596564/pexels-photo-1596564.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
anb:
"https://images.pexels.com/photos/316776/pexels-photo-316776.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
tam:
"https://images.pexels.com/photos/3045635/pexels-photo-3045635.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
};
const navItems = $(".nav li");
const imgBox = $(".banner-img")[0];
navItems.on("click", function (el) {
imgBox.src = imgUrls[el.target.id];
});
});
codepen.io
You can do like this :
Html:
<div id="header">
<img src="../images/nagam1.png">
<ul id="imageLinks">
<li>Vasantha</li>
<li>Anbalagan</li>
<li>Tamilmani</li>
</ul>
</div>
<div>
<img id="myBanner" src="Image-1.jpg">
</div>
Script:
<script>
$(document).ready(function () {
$("#imageLinks a").click(function () {
$("#myBanner").attr("src",this.id+".jpg");;
});
});
</script>

Change content and target of anchor tag on click

I am using the onclick method on a link ("MENU") to display a div (#topmenu) when clicked, but how do I change the text of the anchor tag to "CLOSE" when div (#topmenu) appears and make the div disappear when "CLOSE" is clicked? Could it be achieved without using jQuery?
function view() {
document.getElementById('topmenu').setAttribute('style', 'display:block');
}
body * {
box-sizing: border-box;
}
#media only screen and (max-width: 1200px) {
.bar {
width: 80%;
margin: auto;
}
}
#media only screen and (min-width: 1201px) {
.bar {
width: 1000px;
margin: auto;
}
}
.bar {
display: flex;
justify-content: center;
position: relative;
}
.img img {
display: block;
}
.button span {
position: absolute;
right: 0;
top: 40%;
}
#topmenu {
display:none;
clear: both;
height:80vh;
vertical-align: middle;
text-align: center;
}
#topmenu ul {
list-style: none;
}
<div class="bar">
<div class="img">
<img src="<?php bloginfo('stylesheet_directory'); ?>/images/santorini-wedding-photographer-logo.png">
</div>
<div class="button">
<span style="float: right;">MENU</span>
</div>
</div>
<div id="topmenu">
<div style="text-align: left;">
<ul>
<li>About</li>
</ul>
</div>
</div>
Apply a class to the topmenu instead of changing the style.
function view(event){
event.preventDefault();
document.querySelector("#topmenu").classList.toggle('open');
if(event.target.innerHTML === "CLOSE")
event.target.innerHTML = "MENU"
else
event.target.innerHTML = "CLOSE"
}
You need to pass event to your onclick function
MENU
in your css
#topmenu.open{
display:block
}
function view(event){
document.querySelector("#menu").classList.toggle('red');
if(event.target.innerHTML === "Red")
event.target.innerHTML = "Blue"
else
event.target.innerHTML = "Red"
}
#menu{
width:100px;
height:100px;
background:blue;
transition:background 200ms;
}
#menu.red{
background:red;
}
<a onClick="view(event)" href="#">Red</a>
<div id="menu"></div>
There are many different ways that you can do this using vanilla JavaScript. You can do this easily by setting the a tag to have id="text" and changing the text with a conditional statement that determines what the current value of the text is.
If the text is currently "MENU", it should be changed to "CLOSE" and set display: block. If the text is currently "CLOSE", it should change it back to "MENU" and toggle the topmenu id to be invisible. You can also toggle the styling itself by using toggle.
if (document.getElementById('text').innerHTML === 'MENU'){
document.getElementById('text').innerHTML = 'CLOSE';
document.getElementById('topmenu').setAttribute('style', 'display:block');
}
else {
document.getElementById('text').innerHTML = 'MENU';
document.getElementById('topmenu').setAttribute('style', 'visibility:hidden');
}
body * {
box-sizing: border-box;
}
#media only screen and (max-width: 1200px) {
.bar {
width: 80%;
margin: auto;
}
}
#media only screen and (min-width: 1201px) {
.bar {
width: 1000px;
margin: auto;
}
}
.bar {
display: flex;
justify-content: center;
position: relative;
}
.img img {
display: block;
}
.button span {
position: absolute;
right: 0;
top: 40%;
}
#topmenu {
display: none;
clear: both;
height: 80vh;
vertical-align: middle;
text-align: center;
}
#topmenu ul {
list-style: none;
}
<div class="bar">
<div class="img">
<img src="<?php bloginfo('stylesheet_directory'); ?>/images/santorini-wedding-photographer-logo.png">
</div>
<div class="button">
<span style="float: right;"><a id="text" href="#!" onclick="view()">MENU</a></span>
</div>
</div>
<div id="topmenu">
<div style="text-align: left;">
<ul>
<li>About</li>
</ul>
</div>
</div>
<script>
function view() {
if (document.getElementById('text').innerHTML === 'MENU') {
document.getElementById('text').innerHTML = 'CLOSE';
document.getElementById('topmenu').setAttribute('style', 'display:block');
} else {
document.getElementById('text').innerHTML = 'MENU';
document.getElementById('topmenu').setAttribute('style', 'visibility:hidden');
}
}
</script>
Try this solution using pure JavaScript.
var menu = document.getElementById("top-menu");
var btn = document.getElementById("menu-btn");
btn.addEventListener("click",function(e){
menu.classList.toggle("open");
if(e.target.textContent == "MENU"){
e.target.textContent = "CLOSE";
}
else {
e.target.textContent = "MENU";
}
});
#top-menu {
display: none;
}
.open {
display: block !important;
}
<div id="top-menu">My Meny</div>
MENU
Try this
let isDisplayed = false;
function view() {
isDisplayed = !isDisplayed;
document.getElementById('topmenu').style.display = isDisplayed?'block':'none';
document.querySelector('[onclick="view()"]').innerText = isDisplayed ? 'CLOSE':'MENU';
}

setting position to absolute and top to 0 in css causing javascript classList.toggle() to not work

I'm using the following javascript function to toggle a nav menu:
var navList = document.getElementById("navbar-list-landing");
var openBtn = document.getElementById("nav-open-landing");
function toggleNav() {
navList.classList.toggle("open");
}
It works fine until I add the following CSS to the id of the ul I'm trying to hide:
position: absolute;
top: 0;
The javascript function then will not run at all (using a console.log at the beginning of the function).
I'm including a code snippet of the entire nav below (stripped of all but the necessary CSS so it's a little ugly).
var navList = document.getElementById("navbar-list-landing");
var openBtn = document.getElementById("nav-open-landing");
function toggleNav() {
console.log("test");
navList.classList.toggle("open");
}
#nav-landing {
position: fixed;
background: #fff;
height: 82px;
width: 100%;
}
#nav-landing #nav-logo-landing {
display: block;
float: left;
width: 220px;
}
#nav-landing #navbar-list-landing {
position: absolute;
top: 0;
height: 100vh;
width: 100vw;
opacity: 0;
margin: 0;
}
#nav-landing #dropdown-more {
display: none;
}
#nav-landing #nav-open {
display: inline-block;
background: #fff;
width: 20%;
height: 100%;
border: 1px solid black;
}
#nav-landing .open {
opacity: 1 !important;
}
<nav class="nav clearfix" id="nav-landing">
<img src="./img/lenus-logo.png" alt="Lenus Logo" id="nav-logo-landing" />
=
<ul class="navbar-list" id="navbar-list-landing">
<li class="navbar-item">Home</li>
<li class="navbar-item">About Us</li>
<li class="navbar-item">Services</li>
<li class="navbar-item">Macra</li>
<li class="navbar-item">Schedule a Consult</li>
<li class="navbar-item">More</li>
</ul>
<div class="dropdown" id="dropdown-more">
<ul class="navbar-sublist" id="#sublist-more">
<li class="navbar-subitem">Careers</li>
<li class="navbar-subitem">Contact</li>
</ul>
</div>
</nav>
Thanks in advance.

Iterating over multiple <ul> items to make a jQuery script work without repeating code

I have implemented a jQuery 'magic line' in my multi-level navigation menu and it seems to work with the first sub-navigation, but if I add more it breaks.
My question is: How do I iterate over the other sub-navigation menus to get it to work across however many sub-level items I may add? ( <ul class="sy__list__secondary"> )
Please take a look at my code below. To reproduce my problem follow these steps:
Hover over the first child in the main navigation (HOME)
Then hover over the children of the 'HOME' item - the magic line will work perfectly.
Now hover over the second child in the main navigation (ABOUT)
Then hover over the children of the 'ABOUT' list - the magic line will not work.
My question is: How do I iterate over the other sub-navigation menus to get it to work across however many sub-level items I may add?
var $el, leftPos, newWidth;
$('.sy__list__secondary').each(function() {
$(this).append("<li id='magic-line'></li>");
});
/* Cache it */
var $magicLine = $("#magic-line");
function magicLinePref() {
$magicLine
.width($(".sy__list__secondary.active li:first-child").width())
.css("left", $(".sy__list__secondary.active li:first-child").position().left)
.data("origLeft", $magicLine.position().left)
.data("origWidth", $magicLine.width());
$(".sy__list__secondary li").find("a").hover(function() {
$el = $(this);
leftPos = $el.position().left;
newWidth = $el.parent().width();
$magicLine.stop().animate({
left: leftPos,
width: newWidth
});
}, function() {
$magicLine.stop().animate({
left: $magicLine.data("origLeft"),
width: $magicLine.data("origWidth")
});
});
}
$('.sy__list__primary > li').hover(function() {
magicLinePref();
});
.sy__navigation {
position: relative;
}
.sy__navigation__primary {
background: #333333;
}
.sy__navigation__secondary {
position: absolute;
background: #031f37eb;
left: 0;
top: 50px;
z-index: 10;
width: 100%;
display: none;
}
#magic-line {
position: absolute;
bottom: 0;
padding: 0 !important;
left: 0;
width: 100px;
height: 2px;
background: #31B2E7;
}
.sy__list__primary>li:hover .sy__navigation__secondary {
display: block;
}
ul.sy__list__secondary {
justify-content: space-around;
margin: auto;
padding: 0;
color: #ffffff;
}
ul.sy__list__primary {
margin: auto;
padding: 0;
box-sizing: border-box;
}
ul.sy__list__primary span,
a {
color: #ffffff;
}
ul.sy__list__primary li {
display: inline-block;
letter-spacing: 1px;
font-size: 10px;
box-sizing: border-box;
}
ul.sy__list__primary>li {
padding: 20px;
}
ul.sy__list__secondary li a {
padding: 15px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<div class="sy__navigation">
<div class="sy__navigation__primary">
<div class="container">
<div class="row">
<ul class="sy__list__primary">
<li><span>HOME</span>
<div class="sy__navigation__secondary">
<ul class="sy__list__secondary active">
<li>SUB 1A</li>
<li>SUB 1A</li>
<li>SUB 1A</li>
</ul>
</div>
</li>
<li><span>ABOUT</span>
<div class="sy__navigation__secondary">
<ul class="sy__list__secondary">
<li>SUB 2A</li>
<li>SUB 2A</li>
<li>SUB 2A</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
Updated magicLinePref() function and passed respective li object. Fetched .sy__list__secondary and .#magic-line using li.find.
Removed global declaration of var $magicLine = $("#magic-line");. As when jQuery select any object with id selector # it will only return first object found with given id.
Instead of that I have select element which are inside current li element which is passing from magicLinePref($(this));.
li.find("#magic-line"); find element with id magic-line inside current li. Similarly for class selector .sy__list__secondary.
var $el, leftPos, newWidth;
$('.sy__list__secondary').each(function() {
$(this).append("<li id='magic-line'></li>");
});
/* Cache it */
function magicLinePref(li) {
var $magicLine = li.find("#magic-line");
$magicLine
.width(li.find(".sy__list__secondary li:first-child").width())
.css("left", li.find(".sy__list__secondary li:first-child").position().left)
.data("origLeft", $magicLine.position().left)
.data("origWidth", $magicLine.width());
li.find(".sy__list__secondary li").find("a").hover(function() {
$el = $(this);
leftPos = $el.position().left;
newWidth = $el.parent().width();
$magicLine.stop().animate({
left: leftPos,
width: newWidth
});
}, function() {
$magicLine.stop().animate({
left: $magicLine.data("origLeft"),
width: $magicLine.data("origWidth")
});
});
}
$('.sy__list__primary > li').hover(function() {
magicLinePref($(this));
});
.sy__navigation {
position: relative;
}
.sy__navigation__primary {
background: #333333;
}
.sy__navigation__secondary {
position: absolute;
background: #031f37eb;
left: 0;
top: 50px;
z-index: 10;
width: 100%;
display: none;
}
#magic-line {
position: absolute;
bottom: 0;
padding: 0 !important;
left: 0;
width: 100px;
height: 2px;
background: #31B2E7;
}
.sy__list__primary>li:hover .sy__navigation__secondary {
display: block;
}
ul.sy__list__secondary {
justify-content: space-around;
margin: auto;
padding: 0;
color: #ffffff;
}
ul.sy__list__primary {
margin: auto;
padding: 0;
box-sizing: border-box;
}
ul.sy__list__primary span,
a {
color: #ffffff;
}
ul.sy__list__primary li {
display: inline-block;
letter-spacing: 1px;
font-size: 10px;
box-sizing: border-box;
}
ul.sy__list__primary>li {
padding: 20px;
}
ul.sy__list__secondary li a {
padding: 15px;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<div class="sy__navigation">
<div class="sy__navigation__primary">
<div class="container">
<div class="row">
<ul class="sy__list__primary">
<li><span>HOME</span>
<div class="sy__navigation__secondary">
<ul class="sy__list__secondary">
<li>SUB 1A</li>
<li>SUB 1A</li>
<li>SUB 1A</li>
</ul>
</div>
</li>
<li><span>ABOUT</span>
<div class="sy__navigation__secondary">
<ul class="sy__list__secondary">
<li>SUB 2A</li>
<li>SUB 2A</li>
<li>SUB 2A</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>

When click on second dropdown black box should remain visible

In this dropdown nav I'm building if a dropdown is opened and you click to open a second one, the black box should remain visible. At the moment the black box disappears when you click on a second dropdown and reappears after the dropdown is completely opened.
Update
I also noticed the black box shows after a dropdown is open and it should open at the same time.
I hope this makes sense and thank you for your help!
$(document).ready(function() {
$(".click").on("click", function(e) {
var menu = $(this);
toggleDropDown(menu);
});
$(document).on('mouseup',function(e) {
var container = $("nav .top-bar-section ul");
// if the target of the click isn't the container nor a descendant of the container
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if ($('a.active').hasClass('active')) {
$('a.active').removeClass('active');
}
});
}
});
});
function toggleDropDown(menu) {
var isActive = $('a.active').length;
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if (menu.hasClass('active')) {
menu.removeClass('active');
} else {
$('a.active').removeClass('active');
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
});
if (!isActive) {
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.nav-wrapper {
width: 100%;
overflow: hidden;
background: #424242;
}
nav {
width: 1024px;
margin: auto;
overflow: hidden;
background: #424242;
}
.nav-content {
width: 100%;
z-index: 999;
background: #ccc;
}
.top-bar-section {
float: left;
}
.top-bar-section a.active {
background: #f00;
}
.showup {
display: none;
background: #ccc;
position: absolute;
width: 100%;
top: 70px;
left: 0;
z-index: 99;
padding: 30px 15px 30px 20px;
}
p {
font-size: 14px;
line-height: 1.4;
}
li.nav-item {
display: inline-block;
background: #f5f5f5;
}
li.nav-item a {
display: block;
text-decoration: none;
padding: 10px;
}
.main-container {
width: 80%;
height: 400px;
margin: auto;
}
.black-bg {
background: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav-wrapper">
<nav>
<div class="top-bar-section">
<ul>
<li class="nav-item">
Nav item 1
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 1.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 2
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 2.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 3
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 3.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 4
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 4.
</p>
</div>
</div>
</li>
</ul>
</div>
</nav>
</div>
<div class="main-container">
</div>
If you want black-bg being added once the menu is clicked, then do not remove and add black-bg class on every click event. Simply add it once if the menu have active class and remove it when menu do not active class. If you remove and add class on every click event then black-bg will first disappear and again it will appear. To black-bg at the time drop-down is open then remove $(".main-container").addClass("black-bg"); from callback function of slideDown() because a callback function is executed after the current effect is finished.
$(document).ready(function() {
$(".click").on("click", function(e) {
var menu = $(this);
toggleDropDown(menu);
});
$(document).on('mouseup',function(e) {
var container = $("nav .top-bar-section ul");
// if the target of the click isn't the container nor a descendant of the container
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if ($('a.active').hasClass('active')) {
$('a.active').removeClass('active');
}
});
}
});
});
function toggleDropDown(menu) {
var isActive = $('a.active').length;
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
if (menu.hasClass('active')) {
menu.removeClass('active');
$(".main-container").removeClass("black-bg");
} else {
$('a.active').removeClass('active');
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
});
}
});
if (!isActive) {
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500);
$(".main-container").addClass("black-bg");
}
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.nav-wrapper {
width: 100%;
overflow: hidden;
background: #424242;
}
nav {
width: 1024px;
margin: auto;
overflow: hidden;
background: #424242;
}
.nav-content {
width: 100%;
z-index: 999;
background: #ccc;
}
.top-bar-section {
float: left;
}
.top-bar-section a.active {
background: #f00;
}
.showup {
display: none;
background: #ccc;
position: absolute;
width: 100%;
top: 70px;
left: 0;
z-index: 99;
padding: 30px 15px 30px 20px;
}
p {
font-size: 14px;
line-height: 1.4;
}
li.nav-item {
display: inline-block;
background: #f5f5f5;
}
li.nav-item a {
display: block;
text-decoration: none;
padding: 10px;
}
.main-container {
width: 80%;
height: 400px;
margin: auto;
}
.black-bg {
background: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav-wrapper">
<nav>
<div class="top-bar-section">
<ul>
<li class="nav-item">
Nav item 1
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 1.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 2
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 2.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 3
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 3.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 4
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 4.
</p>
</div>
</div>
</li>
</ul>
</div>
</nav>
</div>
<div class="main-container">
</div>
Just move $(".main-container").removeClass("black-bg"); into if (menu.hasClass('active')) {
$(document).ready(function() {
$(".click").on("click", function(e) {
var menu = $(this);
toggleDropDown(menu);
});
$(document).on('mouseup',function(e) {
var container = $("nav .top-bar-section ul");
// if the target of the click isn't the container nor a descendant of the container
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if ($('a.active').hasClass('active')) {
$('a.active').removeClass('active');
}
});
}
});
});
function toggleDropDown(menu) {
var isActive = $('a.active').length;
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
//$(".main-container").removeClass("black-bg"); FROM HERE
if (menu.hasClass('active')) {
menu.removeClass('active');
$(".main-container").removeClass("black-bg"); // TO HERE
} else {
$('a.active').removeClass('active');
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
});
if (!isActive) {
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.nav-wrapper {
width: 100%;
overflow: hidden;
background: #424242;
}
nav {
width: 1024px;
margin: auto;
overflow: hidden;
background: #424242;
}
.nav-content {
width: 100%;
z-index: 999;
background: #ccc;
}
.top-bar-section {
float: left;
}
.top-bar-section a.active {
background: #f00;
}
.showup {
display: none;
background: #ccc;
position: absolute;
width: 100%;
top: 70px;
left: 0;
z-index: 99;
padding: 30px 15px 30px 20px;
}
p {
font-size: 14px;
line-height: 1.4;
}
li.nav-item {
display: inline-block;
background: #f5f5f5;
}
li.nav-item a {
display: block;
text-decoration: none;
padding: 10px;
}
.main-container {
width: 80%;
height: 400px;
margin: auto;
}
.black-bg {
background: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav-wrapper">
<nav>
<div class="top-bar-section">
<ul>
<li class="nav-item">
Nav item 1
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 1.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 2
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 2.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 3
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 3.
</p>
</div>
</div>
</li>
<li class="nav-item">
Nav item 4
<div class="showup">
<div class="nav-content">
<p>
Dropdown for Nav Item 4.
</p>
</div>
</div>
</li>
</ul>
</div>
</nav>
</div>
<div class="main-container">
</div>
Is this what you are looking for?
$(document).ready(function() {
$(".click").on("click", function(e) {
var menu = $(this);
toggleDropDown(menu);
});
$(document).on('mouseup',function(e) {
var container = $("nav .top-bar-section ul");
// if the target of the click isn't the container nor a descendant of the container
if (!container.is(e.target) && container.has(e.target).length === 0) {
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
$(".main-container").removeClass("black-bg");
if ($('a.active').hasClass('active')) {
$('a.active').removeClass('active');
}
});
}
});
});
function toggleDropDown(menu) {
var isActive = $('a.active').length;
$('a.active').parent().find('.showup').stop(true, true).slideUp(500, function() {
if (menu.hasClass('active')) {
menu.removeClass('active');
} else {
$('a.active').removeClass('active');
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
});
if (!isActive) {
menu.addClass('active');
menu.parent().find('.showup').stop(true, true).slideDown(500, function() {
$(".main-container").addClass("black-bg");
});
}
The black box will remain there in this case. What you were previously doing was that you were removing black-box explicitly.

Categories

Resources