JS dropdown menu being hidden? or not working? - javascript

After thoroughly trying to fix this issue - I need a little help.
I am trying to make a website that has a navbar (made with bootstrap) for websites and I am making a small drop-down menu for smaller screens (I haven't added this functionality yet, I just want it to work first). I haven't styled it much yet either.
The problem is that I know my button and code is working (because I have a codepen showing that it works), but in my website, I cannot see the drop-down menu. Not sure if it is hidden or what but I just can't figure this out.
Here is the HTML (because I have to put something...):
<div class = "dropdown">
<button onclick = "menuBtn ()" class = "dropBtn">Menu</button>
<div id = "dropCollapse" class = "dropdownContent">
<a class = "contentLinks" href = "#about">About</a>
<a class = "contentLinks" href = "#team">Team</a>
<a class = "contentLinks" href = "#photos">Photos</a>
<a class = "contentLinks" href = "#shirts">T-Shirts</a>
<a class = "contentLinks" href = "#contact">Contact</a>
</div>
</div>
I have played around with z-index (in a number of places but if you have a suggestion, feel free to make it and I will try it). I have taken the menu out of the navbar (thinking it had something to do with that). But mostly I am just confused - nothing else really answered my question about this menu issue. I feel like there is something small that I am overlooking and I just can't figure it out.
Here is a fiddle showing the basic outline of my website with the menu not working: https://jsfiddle.net/nekochan/eh69segg/1/

A few things I noticed:
you were using jQuery but did not define jQuery to load. If you do an "inspect element" you'll see that $ is not defined
also you had a few missing divs, and an anchor wasn't closed
I'd recommend just using purely jQuery if you're going to go that approach - it's a very simple example. Here is your updated fiddle - notice the toggle animates nicely :)
https://jsfiddle.net/qdL9mch2/1/
/* global $ */
$(document).ready(function() {
//makes the masethead fit the whole screen
$("#masthead").css("min-height", $(window).height());
//mobile menu button collapse
$(".dropBtn").on("click", function(){
$("#dropCollapse").toggle("show");
});
// Close the dropdown menu if the user clicks outside of it
//update to jquery
window.onclick = function(event) {
if (!event.target.matches('.dropBtn')) {
var dropdowns = document.getElementsByClassName("dropdownContent");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
};
});

there are multiple errors there in your HTML for example <a class="navBrand" href="#masthead"> is not closing and your menuBtn is not being called, I would recommend you to use jquery completely if you have it included inside your project see here your code working
//mobile menu button collapse
function menuBtn() {
document.getElementById("dropCollapse").classList.toggle("show");
}
/* global $ */
$(document).ready(function() {
$("#my-button").click(function() {
document.getElementById("dropCollapse").classList.toggle("show");
})
//makes the masethead fit the whole screen
$("#masthead").css("min-height", $(window).height());
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropBtn')) {
var dropdowns = document.getElementsByClassName("dropdownContent");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
};
});
.main {
font-family: 'Roboto', sans-serif;
width: 100%;
margin: 0px;
padding: 0px;
overflow-x: hidden;
overflow-y: hidden;
}
.body {
position: relative;
}
#navBar {
margin-bottom: 0;
background-color: black;
font-family: 'Permanent Marker', cursive;
}
.brandImage {
height: 60px;
width: auto;
}
#navHeader {}
#navItem {}
#navLink {
text-decoration: none;
}
.dropBtn {
background-color: #4caf50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropBtn:hover,
.dropBtn:focus {
background-color: #3e8e41;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdownContent {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 9999;
}
.contentLinks {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.contentLinks:hover {
background-color: #f1f1f1;
}
.show {
display: block;
}
#media (max-width: 960px) {
#large-menu {
display: none;
}
.brandImage {
float: left;
}
}
#masthead {
background-color: #65737e;
background-image: url(https://static.pexels.com/photos/285286/pexels-photo-285286.jpeg);
width: 100%;
height: auto;
background-size: cover;
background-position: bottom center;
display: flex;
align-items: center;
min-height: 100%;
min-height: 100vh;
}
.headerText {
font-size: 90px;
font-family: 'Permanent Marker', cursive;
color: #fff;
}
.headerTagline {
font-size: 60px;
font-family: 'Permanent Marker', cursive;
color: #fff;
}
.anchor {
display: block;
height: 50px;
margin-top: -50px;
visibility: hidden;
}
.sectionHeader {
font-family: 'Permanent Marker', cursive;
padding: 20px 20px 20px 20px;
}
.sectionText {
padding: 20px 20px 20px 20px;
}
#aboutBox {
background-color: #c0c5ce;
padding: 20px 0 20px;
}
#teamBox {
background-color: #a7adba;
padding: 20px 0 20px;
}
#workBox {
background-color: #65737e;
padding: 20px 0 20px;
}
#shirtBox {
background-color: #4f5b66;
padding: 20px 0 20px;
}
#socialBox {
background-color: #343d46;
padding: 20px 0 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<nav class="navbar navbar-inverse navbar-fixed-top" id="navBar">
<div class="container-fluid">
<div class="navHeader navbar-left">
<a class="navBrand" href="#masthead"></a>
<ul class="nav navbar-nav navbar-right" id="large-menu">
<li class="navItem">
<a class="navLink" href="#about">About</a>
</li>
<li class="navItem">
<a class="navLink" href="#team">Team</a>
</li>
<li class="navItem">
<a class="navLink" href="#photos">Photos</a>
</li>
<li class="navItem">
<a class="navItem" href="#shirts">T-Shirts</a>
</li>
<li class="navItem">
<a class="navLink" href="#contact">Contact</a>
</li>
</ul>
</div>
<div class="dropdown">
<button class="dropBtn" id="my-button">Menu</button>
<div id="dropCollapse" class="dropdownContent">
<a class="contentLinks" href="#about">About</a>
<a class="contentLinks" href="#team">Team</a>
<a class="contentLinks" href="#photos">Photos</a>
<a class="contentLinks" href="#shirts">T-Shirts</a>
<a class="contentLinks" href="#contact">Contact</a>
</div>
</div>
</nav>
<div class="container text-center" id="masthead">
<div class="col-sm-12">
<h1 class="headerText"></h1>
<p class="headerTagline"></p>
</div>
</div>
<span class="anchor" id="about"></span>
<div class="container-fluid" id="aboutBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">About Us</h2>
<p class="sectionText">We're all about that chedda</p>
</div>
</div>
</div>
<span class="anchor" id="team"></span>
<div class="container-fluid" id="teamBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">Meet the team</h2>
<p class="sectionText">pictures of team go here</p>
</div>
</div>
</div>
<span class="anchor" id="photos"></span>
<div class="container-fluid" id="workBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">Our Work</h2>
<p class="sectionText">pictures go here</p>
</div>
</div>
</div>
<span class="anchor" id="shirts"></span>
<div class="container-fluid" id="shirtBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">T-shirts Preview</h2>
<p class="sectionText">pictures of tshirts go here</p>
</div>
</div>
</div>
<span class="anchor" id="contact"></span>
<div class="container-fluid" id="socialBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">Contact Us</h2>
<p class="sectionText">links to social media and contact us form</p>
</div>
</div>
</div>

Related

How to add mutually exclusivity on toggling dropdown menu

I have a menu with dropdown submenus. I'm trying to close an item when clicking on another, so that I don't have multiple items open at the same time. In a previous question: How to Apply .nextElementSibling to the next item of a dropdown menu a user suggested that I take a look at the function called mutually exclusivity. How can I add it to my menu?
var dropdownBtn = document.querySelectorAll('.menu-btn');
dropdownBtn.forEach(btn => btn.addEventListener('click', function() {
var menuContent = this.nextElementSibling;
menuContent.classList.toggle("show");
}));
.menu-btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.menu-btn:hover {
background: #000;
color: #fff;
}
.drop_container {
display: none;
background-color: #017575;
transition: 0.3s;
opacity: 0;
}
.drop_container.show {
display: contents;
visibility: visible;
opacity: 1;
}
.drop_container > .item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown-menu">
<div class="menu-btn">One</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="menu-btn">Two</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>
Store previously clicked menu in a variable, and clear it's class if another menu was clicked
var dropdownBtn = document.querySelectorAll('.menu-btn'),
lastOpened = null;
dropdownBtn.forEach(btn => btn.addEventListener('click', function() {
var menuContent = this.nextElementSibling;
menuContent.classList.toggle("show");
if (lastOpened && lastOpened !== menuContent)
lastOpened.classList.remove("show");
lastOpened = menuContent;
}));
.menu-btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.menu-btn:hover {
background: #000;
color: #fff;
}
.drop_container {
display: none;
background-color: #017575;
transition: 0.3s;
opacity: 0;
}
.drop_container.show {
display: contents;
visibility: visible;
opacity: 1;
}
.drop_container > .item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown-menu">
<div class="menu-btn">One</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="menu-btn">Two</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>
You could add a function that closes all menu's except the one you pass into it:
var dropdownBtn = document.querySelectorAll('.menu-btn');
dropdownBtn.forEach(btn => btn.addEventListener('click', function() {
var menuContent = this.nextElementSibling;
closeMenusExcept(menuContent);
menuContent.classList.toggle("show");
}));
function closeMenusExcept(menuContent) {
dropdownBtn.forEach((element) => {
if (menuContent !== element.nextElementSibling) {
element.nextElementSibling.classList.remove("show");
}
})
}
.menu-btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.menu-btn:hover {
background: #000;
color: #fff;
}
.drop_container {
display: none;
background-color: #017575;
transition: 0.3s;
opacity: 0;
}
.drop_container.show {
display: contents;
visibility: visible;
opacity: 1;
}
.drop_container>.item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown-menu">
<div class="menu-btn">One</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="menu-btn">Two</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>
Note
I changed the class names so they easier to type and read.
We'll use the programming paradigm call event delegation.
Bind event to an ancestor tag (a tag that holds all of the tags you want to control)
Figure I
const menu = document.querySelector(".dropdown");
menu.addEventListener('click', //...
Next, design an event handler that only reacts when the right tags are clicked
Figure II
//...
function(event) {
// This is the tag the user clicked
const clicked = event.target;
// Find .show
const current = document.querySelector('.show');
// See if the clicked tag has .show class
let state = clicked.matches('.show');
// Only react if the clicked tag has .btn class
if (clicked.matches('.btn')) {//...
Note: The .show class is now assigned to the .btn. See Figure IV
Figure III
//...
// if there already is a .show
if (current) {
// remove .show
current.classList.remove('show');
}
// if the clicked tag did not have .show previously...
if (!state) {
// ...add .show to it
clicked.classList.add("show");
}
}
});
In CSS this ruleset uses the adjacent sibling combinator which is equivalent to .nextElementSibling
Figure IV
/* .btn.show + .list <=that's the next sibling */
.show+.list {
display: block;
}
Removed visibility and opacity since original state is display:none which is a switch that inhibits any sort of transition (also removed). The display: content was changed to display: block. display: content doesn't have any standard behavior, when applied, the .items were black and white, but once replaced their original green returned. As a general rule dealing with CSS is if you don't see it being used in the examples, don't use it because there's probably a good reason why it isn't being used.
With this setup you never have to worry about how many button/items you have as long as it is inside the ancestor tag. Also, if you add any button/items dynamically, they do not need to be bound to the event. All you'll ever need is one event listener for each event you want to listen for.
const menu = document.querySelector(".dropdown");
const btns = document.querySelectorAll('.btn');
menu.addEventListener('click', function(event) {
const clicked = event.target;
const current = document.querySelector('.show');
let state = clicked.matches('.show');
if (clicked.matches('.btn')) {
if (current) {
current.classList.remove('show');
}
if (!state) {
clicked.classList.add("show");
}
}
});
.btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.btn:hover {
background: #000;
color: #fff;
}
.list {
display: none;
background-color: #017575;
}
.show+.list {
display: block;
}
.list>.item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown">
<div class="btn">One</div>
<div class="list">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="btn">Two</div>
<div class="list">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="btn">Three</div>
<div class="list">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>

Cant make tabs fixed at top under navbar section after clicked

Edit: I added the windo scroll function I make it but the contents under tabs goes over from it. How can I fix that?
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
console.log(true);
$(".tabs").addClass("tabs-position");
} else {
console.log(false);
$(".tabs").removeClass("tabs-position");
}
});
.tabs-position {
margin-bottom: 50px;
position:sticky;
top: 0;
background-color: red;
}
I have a page with a navbar and tabs. When I click them I direct the user to the section in the same page using the id attribute, however my tabs are in the middle of my page which is fine. What I am trying to achieve is to move them under my navbar section when I click them.
I tried after attribute but I don't get it. I have included my code below, How can I replace their position?
<section class="tabs">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="tab-outer">
<div class="tab-list">
<ul>
<li>
Rooms
</li>
<li>
info tab
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</section>
.tabs {
margin-bottom: 50px;
.tab-outer {
border-bottom: 4px solid #f5f5f5;
position: sticky;
top: 70px;
padding: 20px 0 0 0;
}
.tab-list {
a {
color: #4a4947;
}
ul {
padding: 0 30px;
display: flex;
justify-content: space-between;
list-style-type: none;
}
}
}
You cannot nest CSS like that. Instead, use to select siblings at any level. And also, you have to put position:sticky on the direct sibling of an element that is being scrolled.
.tabs {
margin-bottom: 50px;
position: sticky;
top: 0;
background-color: #ffffff;
}
.tabs .tab-outer {
border-bottom: 4px solid #f5f5f5;
top: 70px;
padding: 20px 0 0 0;
}
.tabs .tab-list a {
color: #4a4947;
}
.tabs .tab-list ul {
padding: 0 30px;
display: flex;
justify-content: space-between;
list-style-type: none;
}
<section class="tabs">
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="tab-outer">
<div class="tab-list">
<ul>
<li>
Rooms
</li>
<li>
info tab
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</section>
<div style="height:3600px;width:100%;background-color:blue;color:white;">foo</div>
By using z-index I fixed the problem
.tabs-position {
margin-bottom: 50px;
position:sticky;
top: 0;
background-color: red;
z-index: 1;
}

How to make smooth opening dropdown with basic javascript code?

How can I make the red backgrounded "Content" area open smoothly from top to bottom when click to "Clicker" with this piece of code? And extra question is, how can I add more Clickers in the same Html with the same javascript code? If I duplicate these, only one is working.
function myFunction() {
var x = document.getElementById("myLinks");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
.accordion {
position: relative;
width: 100%;
height: auto;
background:red;
}.grider{
display: block;
width: 100%;
background: #fff;
}
#myLinks {
display:none;
}
.content {
height:50px;}
<div class="accordion">
<a href="javascript:void(0);" onclick="myFunction()" class="grider clearfix toggle">
<span>Clicker</span>
</a>
<div class="content clearfix" id="myLinks">Content</div>
</div>
You don't need Javascript for all animations. Why don't you try with CSS?
const btns = document.querySelectorAll('.btn-dropdown')
btns.forEach(btn => {
btn.addEventListener('click', function(e) {
e.target.classList.toggle('open')
})
})
html,
body {
margin: 0;
font-family: Arial;
}
nav {
display: flex;
}
.btn-dropdown {
position: relative;
cursor: pointer;
padding: 8px 16px;
border: 1px solid gray;
}
.dropdown-content-container {
overflow-y: hidden;
max-height: 0;
transition: all 0.25s;
}
.btn-dropdown.open>.dropdown-content-container {
max-height: 120px;
transition: all 0.4s;
}
<nav>
<div class="dropdown-wrapper">
<div class="btn-dropdown">
CLICK 1
<div class="dropdown-content-container">
<div class="dropdown-content">
DROPDOWN CONTENT 1
</div>
</div>
</div>
</div>
<div class="dropdown-wrapper">
<div class="btn-dropdown">
CLICK 2
<div class="dropdown-content-container">
<div class="dropdown-content">
DROPDOWN CONTENT 2.1<br /> DROPDOWN CONTENT 2.2<br /> DROPDOWN CONTENT 2.3<br /> DROPDOWN CONTENT 2.4<br />
</div>
</div>
</div>
</div>
</nav>

How to close hamburger nav on click of the <a> tags?

As the title states, I am wanting my hamburger navbar to close when I click on the tags I have tried many ways for the last couple hours but am unable to solve my problem?
I Have tried setting the hide() property with jquery but no luck think it may be because i am pretty new to JS and am just wanting to get my website finished.
const menuBtn = document.querySelector(".menu-btn");
const mobileContent = document.querySelector(".mobile-content");
const mobileItem = document.querySelector(".mobile-item");
const mobileItems = document.querySelectorAll(".mobile-items");
// Set Initial State Of Menu
let showMenu = false;
menuBtn.addEventListener("click", toggleMenu);
function toggleMenu() {
if (!showMenu) {
menuBtn.classList.add("close");
mobileContent.classList.add("show");
mobileItem.classList.add("show");
mobileItems.forEach(item => item.classList.add("show"));
// Set Menu State
showMenu = true;
} else {
menuBtn.classList.remove("close");
mobileContent.classList.remove("show");
mobileItem.classList.remove("show");
mobileItems.forEach(item => item.classList.remove("show"));
// Set Menu State
showMenu = false;
}
}
.mobile-nav {
display: block;
position: fixed;
width: 100%;
top: 0;
z-index: 3;
}
.mobile-nav .menu-btn {
position: absolute;
z-index: 3;
right: 20px;
top: 20px;
cursor: pointer;
}
.mobile-nav .menu-btn .btn-line {
width: 28px;
height: 3px;
margin: 0 0 5px 0;
background: #333;
}
.mobile-content {
position: fixed;
top: 0;
width: 100%;
opacity: 0.9;
visibility: hidden;
}
.mobile-content.show {
visibility: visible;
}
.mobile-content .mobile-item {
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
float: right;
width: 100%;
height: 100vh;
overflow: hidden;
margin: 0;
padding: 0;
background: blue;
list-style: none;
transform: translate3d(0, -100%, 0);
}
.mobile-content .mobile-link {
display: inline-block;
position: relative;
font-size: 2rem;
padding: 1rem 0;
font-weight: bold;
color: #333;
text-decoration: none;
}
<!-- Mobile Nav -->
<div class="mobile-nav">
<div class="menu-btn">
<div class="btn-line"></div>
<div class="btn-line"></div>
<div class="btn-line"></div>
</div>
<h2>MATTY</h2>
<nav class="mobile-content">
<ul class="mobile-item">
<li class="mobile-items">
<a href="#about-me" class="mobile-link">
ABOUT
</a>
</li>
<li class="mobile-items">
<a href="#the-portfolio" class="mobile-link">
PORTFOLIO
</a>
</li>
<li class="mobile-items">
<a href="#" class="mobile-link">
BLOG
</a>
</li>
<li class="mobile-items">
<a href="#contact-me" class="mobile-link">
CONTACT
</a>
</li>
</ul>
</nav>
</div>
I had to remove some of your CSS as it was not working in the snippet.
Recommend you use element.classList.toggle() as below.
Note how much simpler the code becomes.
EDIT: Clicking any a tag will now close menu
document.addEventListener("click", (e) => {
if(e.target.matches('.menu-btn')
|| e.target.matches('.btn-line')
|| e.target.matches('a')) {
toggleMenu();
}
});
function toggleMenu() {
document.querySelector('.mobile-content').classList.toggle('hide');
}
.btn-line {
display: block;
width: 50px;
margin: 5px;
border: 2px solid black;
}
.mobile-nav {
display: block;
width: 100%;
z-index: 3;
}
.mobile-content {
position: fixed;
width: 100%;
opacity: 0.9;
}
.hide {
display: none;
}
<!-- Mobile Nav -->
<div class="mobile-nav">
<div class="menu-btn">
<span class="btn-line"></span>
<span class="btn-line"></span>
<span class="btn-line"></span>
</div>
<a href="#home">
<h2>MATTY</h2>
</a>
<nav class="mobile-content hide">
<ul class="mobile-item">
<li class="mobile-items">
<a href="#about-me" class="mobile-link">
ABOUT
</a>
</li>
<li class="mobile-items">
<a href="#the-portfolio" class="mobile-link">
PORTFOLIO
</a>
</li>
<li class="mobile-items">
<a href="#" class="mobile-link">
BLOG
</a>
</li>
<li class="mobile-items">
<a href="#contact-me" class="mobile-link">
CONTACT
</a>
</li>
</ul>
</nav>
</div>
#MPB A good way to dabble into some simple JQuery language is a way to fix your problem. A quick and easy way to make a good Hamburger Navigation menue is with the toggleClass(); function in JQuery. Just make a #keyframes-animation within an un-set class and toggleClass(); will switch between the two seamlessly. I do this all the time, comment if you'd like me to forward the code to you for you to use.

Dynamic popup menu that adds class to parent when radio button is selected (like Trello's)

I want to create a dynamic popup menu that adds a class to "lists" parent when radio button is selected // removes classes when unselected (HTML structure below cannot change...only can change CSS and JS)
I'm trying to make the "List Popup" popup directly under each "Green Gear" icon when clicked on/ hidden when clicked off (css classes).
Whenever a radio button is selected from the popup, I need it to add a class directly into the corresponding list's parent div, while not effecting any of the other lists.
The trick (for me) is making all of this happen dynamically with 1 popup menu that sits outside of each lists divs scope.
The HTML structure cannot be changed (this has to be completely done w/ JS and CSS).
Here's what I've got so far: https://jsfiddle.net/oneeezy/t5eou67k/
$(document).ready(function () {
/* Code to play with for show/hide popup
/* Code to play with for adding/removing classes when radio checked
$('.list-layouts input').click(function () {
$('.list-layouts input:not(:checked)').parent().removeClass("blue");
$('.list-layouts input:checked').parent().addClass("blue");
});
*/
});
/* Reset Styles */
* { box-sizing: border-box; margin: 0; padding: 0; }
h1 { padding: 0 0 .25rem; }
h2 { line-height: 1.6; }
aside { background: #e2e4e6; padding: 1rem; color: gray; margin: 1rem; border: 1px dashed gray; }
aside ul { list-style: inside; }
aside span { font-style: italic; color: rgba(0, 0, 0, .78); }
.page { background: rgba(137, 96, 158, .17); margin: 2rem 0; padding: 2rem; position: relative; }
.page::before { content: "<div> ...Scope"; color: rgba(0, 0, 0, .54); position: absolute; top: 0; left: 0; }
.page::after { content: "</div>"; color: rgba(0, 0, 0, .54); position: absolute; bottom: 0; left: 0; }
.purple { background: rgba(137, 96, 158, .17); }
.green { background: lime; }
.yellow { background: yellow; }
/* Trello (default tyles) */
.wrapper { display: flex; }
.list-wrapper { flex: 1; margin: 10px; }
.list { background: #e2e4e6; position: relative; padding: 0 10px 3px; }
.icon { display: block; position: absolute; top: 0; right: 0; width: 33px; height: 38px; background: lime; text-decoration: none; font-size: 2em; line-height: 1.3; color: darkgreen; }
.card { display: block; height: 50px; background: white; border-radius: 3px; border: 1px solid #ccc; padding: .5em; margin: 0 0 .5em; }
/* List Popup */
.list-popup { display: block; width: 350px; max-height: 800px; background: yellow; border-radius: 3px; border: 1px solid #ccc; padding: 1em; }
.list-popup p { padding: 0 0 1rem; }
.list-popup p span::after { content: "<div class='list-wrapper'>"; }
.list-layouts ul { list-style: none; }
.list-normal { }
.list-normal .list { }
.list-color { }
.list-color .list * { background: skyblue; }
.list-bold { }
.list-bold .list * { font-weight: bold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Description -->
<aside>
<h1>Dynamic popup menu that adds class to lists parent when radio button is selected // removes classes when unselected</h1>
<ul>
<li>I'm trying to make the <span class="yellow">"List Popup"</span> popup directly under each <span class="green">"Green Gear"</span> icon when clicked on/ hidden when clicked off (css classes).</li>
<li>Whenever a radio button is selected from the popup, I need it to add a class directly into the corresponding list's parent div, while not effecting any of the other lists.</li>
<li>The trick (for me) is making all of this happen dynamically with 1 popup menu that sits outside of each <span class="purple">lists divs scope</span>.</li>
</ul>
</aside>
<!-- Lists -->
<div class="page">
<div class="wrapper">
<div class="list-wrapper">
<div class="list">
<h2>List (1)</h2>
⚙
<div class="card">Woohoo! Woohoo! Woohoo! </div>
<div class="card">Woohoo! Woohoo! Woohoo! </div>
<div class="card">Woohoo! Woohoo! Woohoo! </div>
</div>
</div>
<div class="list-wrapper">
<div class="list">
<h2>List (2)</h2>
⚙
<div class="card">Woohoo! Woohoo! Woohoo! </div>
<div class="card">Woohoo! Woohoo! Woohoo! </div>
<div class="card">Woohoo! Woohoo! Woohoo! </div>
</div>
</div>
<div class="list-wrapper">
<div class="list">
<h2>List (3)</h2>
⚙
<div class="card">Woohoo! Woohoo! Woohoo! </div>
<div class="card">Woohoo! Woohoo! Woohoo! </div>
<div class="card">Woohoo! Woohoo! Woohoo! </div>
</div>
</div>
</div>
</div>
<!-- List Layout popup -->
<div class="page">
<div id="listPopup" class="list-popup">
<div>
<h3>List Popup</h3>
<p>These radio buttons should add a special class to the individual <span></span> when clicked on and removed when clicked off!</p>
</div>
<form class="list-layouts">
<ul>
<li>
<input type="radio" name="listLayout" id="listNormal">
<label for="listNormal">Normal</label>
</li>
<li>
<input type="radio" name="listLayout" id="listColor">
<label for="listColor">Bold</label>
</li>
<li>
<input type="radio" name="listLayout" id="listBold">
<label for="listBold">Italic</label>
</li>
</ul>
</form>
</div>
</div>
So first we will add the class to the list wrapper of the lists parent with the following code:
$('.icon').on('click', function () {
if(!$('#listPopup').hasClass("open")){
$('#listPopup').toggleClass("open");
}
$(this).parents('.list-wrapper').siblings().removeClass('blue');
if(!$(this).parents('.list-wrapper').hasClass("blue")){
$(this).parents('.list-wrapper').toggleClass("blue");
}
});
Then we need to create an onchange function for the radios to find this class and add the new class to that list.
$('.list-layouts input').on('change', function () {
var newClass = $(this).attr("id");
// Remove the following statement if you want your classes to stack up
$('.blue').removeClass("listNormal listColor listBold");
$('.blue').addClass(newClass);
});
Here is a working fiddle of the whole thing in action Fiddle

Categories