UPDATE
I discovered I could toggle the data state on click with
$(".list-header").attr("data-state", $(".list-header").hasClass('list-header') ? "hide" : "show");
However, when I click the same header I just opened, it doesn't revert back to its original icon or "hide" state.
How can I toggle the current header back to the data-state="hide" state?
$('.list-header.major').click(function(){
$(".list-header").attr("data-state", $(".list-header").hasClass('list-header') ? "hide" : "show");
$('.list-header.major').next('div').slideUp();
$(this).next('div').toggle();
$('.list-header.major').removeClass('active');
$(this).toggleClass('active');
return false;
});
===========================================================================
I need to be able to toggle the "HEADER"'s so that when the subnav is closed for any of them, the header icon is always set to a + sign, and has a data-state=hide
I found that the state of the headers is always set to active, and that the only way to toggle the + or - sign is to toggle the data-state from show to hide, which would be based on the state of the .col-wrapper classes style being either display:none or display: block.
The question is how to look for the display state of the .col-wrapper class and change the data-state based on whether the .list-header has been clicked or not. I've included screen shots of the states from the fiddle(https://jsfiddle.net/2bu35uLn/3/show/) below.
Essentially, the issue is that the icons aren't toggling back to the plus sign, if the user clicks on another header. This should force any closed list header to go back to the plus sign.
This is the closed state
This is the open state
Notice that the .col-wrapper class has display:block to show the subnav, but the .list-header class is still set to data-state="hide", which keeps the header from being toggled back to the correct state.
I'm trying to target the data-state to change to hide if the .col-wrapper class is display:none, by doing something like this:
$(".list-header").on('click', function(){
if($(this).find(".col-wrapper").css("display", "none")){
force data-state to be hide
}
});
HTML
<div class="inner">
<button data-target="#data-nav-0" data-toggle="collapse" data-state="show" class="list-header major no-style"> <span>HEADER</span> </button>
<div class="col-wrapper collapse in" id="data-nav-0" style="display: block;">
<div class="column">
<ul class="list-unstyled">
<li class="list-header mobile">link</li>
<li class="list-header desktop">head</li>
<li class="mobile chevron-right" data-target="#data-inner-0-0" data-toggle="collapse" data-state="hide">
<button class="no-style sub-header">This should toggle the ul links</button>
</li>
<ul class="inner collapse" id="data-inner-0-0">
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</ul>
</div>
<div class="column">
<ul class="list-unstyled">
<li class="list-header desktop">Link</li>
<li class="mobile chevron-right" data-target="#data-inner-0-1" data-toggle="collapse" data-state="hide">
<button class="no-style sub-header">This should toggle the ul links</button>
</li>
<ul class="inner collapse" id="data-inner-0-0">
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</ul>
</ul>
</div>
</div>
</div>
<div class="inner">
<button data-target="#data-nav-0" data-toggle="collapse" data-state="show" class="list-header major no-style"> <span>HEADER</span> </button>
<div class="col-wrapper collapse in" id="data-nav-0" style="display: block;">
<div class="column">
<ul class="list-unstyled">
<li class="list-header mobile">link</li>
<li class="list-header desktop">head</li>
<li class="mobile chevron-right" data-target="#data-inner-0-0" data-toggle="collapse" data-state="hide">
<button class="no-style sub-header">This should toggle the ul links</button>
</li>
<ul class="inner collapse" id="data-inner-0-0">
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</ul>
</div>
<div class="column">
<ul class="list-unstyled">
<li class="list-header desktop">Link</li>
<li class="mobile chevron-right" data-target="#data-inner-0-1" data-toggle="collapse" data-state="hide">
<button class="no-style sub-header">This should toggle the ul links</button>
</li>
<ul class="inner collapse" id="data-inner-0-0">
<li>link</li>
<li>link</li>
<li>link</li>
<li>link</li>
</ul>
</ul>
</ul>
</div>
</div>
</div>
jQuery
$('.list-header.major').next('div').toggle();
$('.list-header.major').click(function(){
$('.list-header.major').next('div').slideUp();
$(this).next('div').toggle();
$('.list-header').removeClass('active');
$(this).toggleClass('active');
return false;
});
$('.mobile').next('ul').toggle();
$('.mobile').click(function() {
$('.mobile').next('ul').slideUp();
$(this).next('ul').toggle();
$('.mobile button').removeClass('active');
if ($(this).next('ul').is(':visible')) {
$(this).find('button').addClass('active');
}
return false;
});
CSS
button.list-header.major {
&:before,
&:after {
color: $purple;
font-family: 'Material Icons';
font-size: 20px;
position: absolute;
right: 20px;
}
&:before {
content: "\E145"; <--THIS IS A PLUS SIGN
}
&:after {
content: "\E15B"; <--THIS IS A MINUS SIGN
}
}
.sub-header:after{
content: " >";
font-family: 'Material Icons';
display: inline-block;
transform: rotate(0);
font-size: 26px;
color: $white;
position: relative;
top: 8px;
transition: transform .3s;
}
.sub-header.active:after{
content: " v";
color: red;
display: inline-block;
transform: rotate(8deg);
font-size: 26px;
color: $neon-green;
transition: transform .3s;
}
UPDATE WITH SCREENSHOT AND MORE DETAIL
The top navigation should have a + icon, not -. Here you can see the second Header is opened and has the correct -, while the Header above it still has the -, although the contents col-wrapper has collapsed below it:
Changed code together with the author of question. Should work as expected.
$('.list-header.major').click(function(){
if (current !== this)
$(current).attr('data-state', 'hide');
$(this).attr("data-state", $(this).attr('data-state') === 'hide' ? "hide" : "show");
current = this;
$('.list-header.major').next('div').slideUp();
$(this).next('div').toggle();
$('.list-header.major').removeClass('active');
$(this).toggleClass('active');
return false;
});
Here is it the fiddle
Related
I have a menu which opens up a submenu on click.
If a link has a dropdown menu (has class header--has-submenu), then on click, I'm making another element (.header__subContainer) appear.
The issue I'm having is with the logic. For example, in my demo, I have two links, what we deliver and about us, both have submenus.
I want a user to be able to click onto a link to open it and then click on the same link to close it (standard UX).
However, I also want the user to be able to click on one link (let's say 'what we deliver) and then click onto about usto show that menus dropdown (then the user can click theabout us` link again to close the menu).
I've tried toggleClass but this causes issues with the last scenario above.
Here's a demo:
$(".header--has-submenu a.header__parentLink").click(function(e) {
e.preventDefault();
console.log("click");
var id = $(this).attr('data-menu');
// add active state styles to link to showcase which menu is open
$("li.header--has-submenu").removeClass("header--has-submenu--active");
$(this).parent().addClass("header--has-submenu--active");
// open subContainer (black div that contains all submenus)
if ( $(".header__subContainer-menu").hasClass("header__subContainer-menu--active") ){
$(".header__subContainer").removeClass("header__subContainer--active");
} else {
$(".header__subContainer").addClass("header__subContainer--active");
}
// remove active class from submenu, so only one menu is open at one time
$(".header__subContainer-menu").removeClass("header__subContainer-menu--active");
// open the relevant menu
$(this).closest(".header__subContainer").addClass("header__subContainer--active");
$(".header__subContainer-menu[data-menu='"+id+"']").toggleClass("header__subContainer-menu--active");
});
.header {
padding: 30px 0;
}
.header__parentUl * {
color: #FFFFFF;
}
.header__li {
margin: 0 20px;
}
.header__subContainer {
display: none;
}
.header__subContainer--active {
display: block;
}
.header__subContainer-menu {
display: none;
}
.header__subContainer-menu--active {
display: block;
}
.header--has-submenu--active a {
color: green;
}
.background--black {
background: #000000;
}
.reset-list {
list-style-type: none;
margin: 0;
padding: 0;
}
.color--white {
color: #FFFFFF;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<header class="header background--black">
<div class="container">
<div class="col-xl-9 justify-content-end">
<nav class="header__menu">
<ul class="header__parentUl d-flex reset-list">
<li class="header__li header--has-submenu">
<a class="header__parentLink" href="#" data-menu="what-we-deliver">What we deliver</a>
</li>
<li class="header__li header--has-submenu">
<a class="header__parentLink" href="#" data-menu="about-us">About us</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="container-fluid background--black header__subContainer">
<div class="row justify-content-center">
<div class="col-12">
<nav class="header__subContainer-menu" data-menu="what-we-deliver">
<ul class="header__subContainer-ul d-flex reset-list">
<li class="header__subContainer-li">
<a class="header__subContainer-link color--white " href="#">Link 1</a>
</li>
<li class="header__subContainer-li">
<a class="header__subContainer-link color--white " href="#">Link 2</a>
</li>
</ul>
</nav>
<nav class="header__subContainer-menu" data-menu="about-us">
<ul class="header__subContainer-ul d-flex reset-list">
<li class="header__subContainer-li">
<a class="header__subContainer-link color--white " href="#">Link 3</a>
</li>
<li class="header__subContainer-li">
<a class="header__subContainer-link color--white " href="#">Link 4</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</header>
Something like this should work:
$(".header--has-submenu a.header__parentLink").click(function(e) {
e.preventDefault();
let id = $(this).attr('data-menu');
// Check if link already active
let wasOpen = $(this).parent().hasClass("header--has-submenu--active");
// remove all active classes
$(".header--has-submenu").removeClass("header--has-submenu--active");
$(".header__subContainer-menu").removeClass("header__subContainer-menu--active");
$(".header__subContainer").removeClass("header__subContainer--active");
if(!wasOpen){
// the clicked link was not open
// add active classes to the 3 elements
$(this).parent().addClass("header--has-submenu--active");
$('.header__subContainer').addClass('header__subContainer--active');
$(".header__subContainer-menu[data-menu='"+id+"']").addClass("header__subContainer-menu--active");
}
});
I have a function like so which toggles my dropdown menu.
<div class="module widget-handle mobile-toggle right visible-sm visible-xs">
<a id="mobile-nav" href="#">
<div class="container1" onclick="myFunction(this)">
<div class="bar1"></div>
<div class="bar2"></div>
<div class="bar3"></div>.
</div>
</a>
</div>
<script>
function myFunction(x) {
x.classList.toggle('change');
document.body.style.overflow ='hidden'
}
</script>
The last part of it
document.body.style.overflow = 'hidden'
Keeps the page from overflowing at the top when the dropdown menu is open. The problem is that when I click on my menu bars, whilst the overflow disappears, clicking on the bars again reveals the page but locks it due to the overflow being hidden.
I'd like to undo
document.body.style.overflow = 'hidden'
When the menu is closed and the closest I've got to understanding it is the function doBack. Can I somehow add doBack to my existing function?
Mobile page here
It's a WordPress site and the javascript above toggles the dropdown by pressing on the bars. In order to extend the dropdown, I made the class collapse bigger, like so.
#media (max-width: 768px) {
.collapse {
position: absolute;
height: 775px;
background-color: white;
z-index: 99999 !important;
top: 75px;
left: -50px;
line-height: 10px;
}
}
HTML:
<div class="module-group right">
<div class="module left">
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul id="menu" class="menu">
<li id="menu-item-15050" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-15050 dropdown">
<a title="Contact" href="url">Contact
<ul role="menu" class="dropdow n-menu">
</ul>
</a>
</li>
</ul>
</div>
</div>
</div>
You can eliminate the style attribute by using:
document.body.style.overflow = null
You can simply add a new CSS class:
.body-overflow {
overflow: hidden;
}
and in your javascript function add another .classList.toggle() but this time on the body:
function myFunction(x) {
x.classList.toggle('change');
document.body.classList.toggle('body-overflow');
}
I have this problem: I'm making header with responsive size, so when the width less than 1199px, user can see hamburger menu. To open/close menu, I'm using React Hooks and it changes display: block / none. But it has to work only when the screen is less than 1199px, but in my case it works every time, and obviously my header has display: none and there's nothing on page (there's only my logo)
Component's code:
const Header = () => {
const [navBar, showNavBar] = useState(false)
const useNavBar = () => {
showNavBar(!navBar)
}
return (
<header class="header-area main-header">
<div class="container">
<div class="row">
<div class="col-lg-2">
<div class="logo-area">
<a href='#'><img src={logo} alt="logo"/></a>
</div>
</div>
<div class="col-lg-10">
<div onClick={useNavBar} class="custom-navbar">
<span></span>
<span></span>
<span></span>
</div>
<div class="main-menu">
<ul style={navBar === true ? {display: 'block'} : {display: 'none'}}> // problem is here
<li class="active">home</li>
<li>about us</li>
<li>schedule</li>
<li>trainers</li>
<li>blog
<ul class="sub-menu">
<li>Blog Home</li>
<li>Blog Details</li>
</ul>
</li>
<li>contact</li>
<li>pages
<ul class="sub-menu">
<li>Service</li>
<li>Elements</li>
</ul>
</li>
<li class="menu-btn">
book now
</li>
</ul>
</div>
</div>
</div>
</div>
</header>
);
}
SASS code:
.main-menu
ul
float: right
#include desktop()
display: none
float: left
position: absolute
top: 60px
right: 0
z-index: 4
background: $dark
width: 40%
padding: 20px 20px 30px
PS: I don't want to add all of my CSS code, because it's over 200 strings, just explain me how to change display using media queries in my case
Don't use inline style. Change class names with JavaScript.
Set the display in your stylesheet based on the class name and media queries.
<ul className={navBar === true ? "foo" : "bar"}>
I just want to ask :
how to make the dropdown-menu collpase when the dropdown menu is active?
When the mouse hovers to the sidebar, the active dropdown menu expanded again?
i think i just wondering using hover but it doesnt work when i try it, so i hope someone can help me to solve this?
Simple Concept I Just want :
Mouse:hover to sidebar-icon/burger is clicked => sidebar-expanded => menu list that have:submenu clicked => dropdown-menu displayed => mouseOut from sidebar => icon is-collapsed
Mouse:hover to sidebar-icon again / sidebar:state(active) => dropdown menu is already expanded
well i dont know that you can understand my question or something.. but i hope u can make this auto collapse menu
$(document).ready(function() {
// Sidebar links
$('.sidebar .side-list li a').on('click', function() {
const $this = $(this);
if ($this.parent().hasClass('buka')) {
$this
.parent()
.children('.dropdown-menu')
.slideUp(200, () => {
$this.parent().removeClass('buka');
});
} else {
$this
.parent()
.parent()
.children('li.buka')
.children('.dropdown-menu')
.slideUp(200);
$this
.parent()
.parent()
.children('li.buka')
.children('a')
.removeClass('buka');
$this
.parent()
.parent()
.children('li.buka')
.removeClass('buka');
$this
.parent()
.children('.dropdown-menu')
.slideDown(200, () => {
$this.parent().addClass('buka');
});
}
});
// ٍSidebar Toggle
$('.burger').on('click', e => {
$('.konten').toggleClass('k-kebuka');
$('.sidebar').toggleClass('s-kebuka');
e.preventDefault();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sidebar" class="sidebar bg-cerah">
<div class="sidebar-dalem">
<div class="side-konten">
<ul class="side-list">
<li class="side-item dropdown">
<a class="dropdown-toggle" href="javascript:void(0)">
<span class="side-ikon">ICON</span>
<span class="side-judul">MENU</span>
<span class="panah">[>]</span>
</a>
<ul class="dropdown-menu">
<li>
SUBMENU #1
</li>
<li>
SUBMENU #2
</li>
</ul>
</li>
<li class="side-item dropdown">
<a class="dropdown-toggle" href="javascript:void(0)">
<span class="side-ikon">[X]</span>
<span class="side-judul">MENU #2</span>
<span class="panah">[>] ></span>
</a>
<ul class="dropdown-menu">
<li>
SUBMENU #1
</li>
<li>
SUBMENU #2
</li>
</ul>
</li>
<li class="side-item">
<a class="side-link" href="javascript:void(0)">
<span class="side-ikon">[X]</span>
<span class="side-judul">MENU #3</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div id="konten" class="konten">
<div class="konten-navbar sticky-top">
<ul class="navbar-kiri">
<li>
<a id="burger" href="javascript:void(0)" class="burger">BURGER ICO</a>
</li>
<li>
SEARCH ICO
</li>
</ul>
</div>
</div>
In pure CSS, .menu:hover definitely works, but you have to build the entire menu inside of the element that has the :hover pseudo class and also either touching or overlapping:
.popup {
position: relative;
}
button {
width: 8em;
height: 40px;
}
ul {
position: absolute;
top: 36px;
left: 8px;
background: #eee;
border: 1px solid black;
display: none;
margin: 0;
width: 14em;
min-height: 8em;
padding: 0.5em;
list-style: none;
}
.popup:hover ul {
display: block;
}
<div>
<div class="popup"><button>Menu</button>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</div>
Certainly, you'd need to style everything properly.
I also seem to remember that JQuery has OnMouseEnter and OnMouseLeave events that work kind of like :hover too.
I've used this code for my navbar :
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="#">Brand</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active">
Link
</li>
<li>
Link
</li>
<li class="dropdown">
Dropdown<strong class="caret"></strong>
<ul class="dropdown-menu">
<li>
Something Here
</li>
<li>
Something else here
</li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
Link
</li>
</ul>
</div>
</nav>
The above code is for simple navbar example. As I'm new to stackoverflow and have less reputation so I can't add images to my question.
Simple hover I can make using CSS but I wanted to make a hover in which if the cursor goes to any item on the navbar there is a effect like color water is filling in a glass.
Also I'm very curious about how to make the end of the section or div a little slant with some angle.
Please refer to the following link for reference:
This the template for reference
I'm trying to make a navbar and end of a section exacty like this template.
The template you refer to creates the bottom "slant" with the following CSS:
.section {
position: relative;
}
.section:after {
content: '';
display: block;
position: absolute;
right: 0;
bottom: -195px; /* the height of your image */
left: 0;
z-index: -1;
height: 195px; /* the height of your image */
background: url(path/to/your/image.png) no-repeat 50% 0%;
}