Auto collapse sidebar menu list when lost focus - javascript

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.

Related

Keep sub menu open on hover with javascript

Description : I got a nav bar with my menu and submenu. I use javascript to make the submenu appear on click
Here is my html
<ul class="menu grid-x">
<div class="logo align-self-middle">
LOGO
</div>
<li class="item has-submenu align-self-middle grid-x align-middle">
<a tabindex="0">Société</a>
<ul class="submenu">
<li class="subitem text-left">Présentation</li>
<li class="subitem text-left">Nous rejoindre</li>
<li class="subitem has-submenu text-left"><a tabindex="0">Nos agences</a></li>
<li class="subitem text-left">Nos actualités</li>
</ul>
</li>
<li class="item has-submenu align-self-middle">
<a tabindex="0">Téléphonie</a>
<ul class="submenu">
<li class="subitem text-left">Téléphonie entreprise</li>
<li class="subitem text-left">Flotte mobile</li>
<li class="subitem text-left">Communications unifiées</li>
<li class="subitem text-left">Centre de contact virtuel</li>
<li class="subitem text-left">Centre de contact Multicanal</li>
</ul>
</li>
<ul>
And here is the javascript I use
const items = document.querySelectorAll(".item");
const menu = document.querySelector(".menu");
/* Activate Submenu */
function toggleItem() {
if (this.classList.contains("submenu-active")) {
this.classList.remove("submenu-active");
} else if (menu.querySelector(".submenu-active")) {
menu.querySelector(".submenu-active").classList.remove("submenu-active");
this.classList.add("submenu-active");
} else {
this.classList.add("submenu-active");
}
}
/* Event Listeners */
for (let item of items) {
if (item.querySelector(".submenu")) {
item.addEventListener("click", toggleItem, false);
item.addEventListener("keypress", toggleItem, false);
}
}
And the CSS to make the submenu appear when parent receive the submenu-active class
submenu-active .submenu {
display: block;
position: absolute;
left: 0;
top: 100%;
min-width: 200px;
}
Problem : I would like to make the submenu appear on hover. The mouseover works when I hover the item class div, but submenu disappear when I try to click on one of its elements because I'm not maintaining the item div hover.
I don't want to use jquery and can't figure out a solution. Anyone could help ?
Thanks a lot
Try this code! and add style as you want.
You can include more mouse events add class on hover OR click is up to you.
const items = document.querySelectorAll(".item");
const menu = document.querySelector(".menu");
items.forEach(item => {
item.addEventListener('click', function() {
if ( !item.classList.contains("show") ){
item.classList.add("show")
}else {
item.classList.remove("show")
}
})
})
.has-submenu {
position: relative; }
.submenu {
display: none;
background-color: #ffffff;
position: absolute;
left: 0;
top: 100%;
min-width: 200px;
}
.has-submenu.show .submenu {
display: block ;
}
<ul class="menu grid-x">
<div class="logo align-self-middle">
LOGO
</div>
<li class="item has-submenu align-self-middle grid-x align-middle ">
<a tabindex="0">Société</a>
<ul class="submenu ">
<li class="subitem text-left">Présentation</li>
<li class="subitem text-left">Nous rejoindre</li>
<li class="subitem has-submenu text-left"><a tabindex="0">Nos agences</a></li>
<li class="subitem text-left">Nos actualités</li>
</ul>
</li>
<li class="item has-submenu align-self-middle">
<a tabindex="0">Téléphonie</a>
<ul class="submenu">
<li class="subitem text-left">Téléphonie entreprise</li>
<li class="subitem text-left">Flotte mobile</li>
<li class="subitem text-left">Communications unifiées</li>
<li class="subitem text-left">Centre de contact virtuel</li>
<li class="subitem text-left">Centre de contact Multicanal</li>
</ul>
</li>
<ul>

togggle menu need to open on click and close itself when click the other menu

How can make it make
1- open toggle menu when on click menu (not opened by default)
2- close itself - if click other parent menu
trying to make it work for the project
and i copied from cssdesk
$('.inbox li').click(function(e) {
$('.inbox li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
e.preventDefault();
});
$(document).ready(function () {
$('.tree-toggler').click(function () {
$(this).parent().children('ul.tree').toggle(300);
});
});
<link class="cssdeck" rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css" class="cssdeck">
<ul class="inbox-nav nav" style="border-top: 1px solid #eef1f5; margin-top:10px;" >
<li class="">
<a href="javascript:;" id="fldr3">menu 1
</li>
<li class="">
<a data-title="Inbox" data-type="important" href="javascript:;">2nd Menu</a>
</li>
<li class="">
<a data-title="Sent" data-type="sent" href="javascript:;">menu2</a>
</li>
<li class="divider"></li>
<li class="active tree-toggler">
Toggle menu</li>
<ul class="nav nav-list tree">
<li class="">Link</li>
<li class="">Link</li>
</ul>
</li>
</ul>
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script class="cssdeck" src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
If user click is not neccesary you can do it by CSS, this is an example the 4th menu item has sub menu items
.menu,
.menu-item {
display: inline;
cursor: default;
}
.menu-item.has-subItem {
position: absolute;
}
.menu-item ul {
display: none;
position: absolute;
top: 15px;
left: 0;
padding: 0;
}
.menu-item:hover ul {
display: inline;
}
<ul class='menu'>
<li class='menu-item'>Item 1</li>
<li class='menu-item'>Item 2</li>
<li class='menu-item'>Item 3</li>
<li class='menu-item has-subItem'>Item 4
<ul>
<li class='sub-item'>sub 1</li>
<li class='sub-item'>sub 2</li>
<li class='sub-item'>sub 3</li>
</ul>
</li>
</ul>
In your $('.inbox li').click() function use jquery's .hide() function on the ul.tree element. Since .hide() won't do anything if the element is already hidden, you don't need to check if it needs to be hidden.
(Similarly, you can pull the $this.addClass('active'); statement out of the if, since it simply won't do anything if the class is already added!)

Targeting data-state to toggle nav headers

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

avoid closing the menu if submenu items is clicked

This is a multilevel menu. When i click the link "About" it opens the submenu which contains 3 links Johnny, Julie & Jamie.
When i click "About" again, it closes the menu. Clicking the submenu also closes the menu, and that i want to avoid.
How do i avoid closing the opened submenu, if i click the submenu (Johnny, Julie & Jamie) ?
$('li.parent').click(function() {
$(this).find('.sub-nav').toggleClass('visible');
});
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<li class="parent">About
<ul class="sub-nav">
<li>Johnny
</li>
<li>Julie
</li>
<li>Jamie
</li>
</ul>
</li>
<li class="parent">AnotherLink
<ul class="sub-nav">
<li>Martin
</li>
<li>Rasmus
</li>
<li>Morten
</li>
</ul>
</li>
</ul>
Alternative to stopPropagation approach for child elements would be adding a small check if the clicked element is the current one (and not it's descendants):
$('li.parent').click(function(e) {
if (this === e.target)
$(this).find('.sub-nav').toggleClass('visible');
});
$('li.parent').click(function(e) {
if (this === e.target)
$(this).find('.sub-nav').toggleClass('visible');
});
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<li class="parent">About
<ul class="sub-nav">
<li>Johnny
</li>
<li>Julie
</li>
<li>Jamie
</li>
</ul>
</li>
<li class="parent">AnotherLink
<ul class="sub-nav">
<li>Martin
</li>
<li>Rasmus
</li>
<li>Morten
</li>
</ul>
</li>
</ul>
You need to stopPropagation of event on child anchor elements:
$("li.parent a").click(function(e) {
e.stopPropagation();
});
You need to prevent the click on the .sub-nav element to be transmitted to your event handler: https://api.jquery.com/event.stoppropagation/

YUI Carousel nav buttons under the ordered list

in the YUI Carousel, i want nav button include prev and next buttons showing under the items.by default these buttons placed in upper items and i want placed those after the items (or images)
<div id="container">
<ol id="carousel">
<li>
1111111
</li>
<li>
222222
</li>
<li>
3333333
</li>
<li>
444444
</li>
<li>
5555555
</li>
<li>
66666666
</li>
<li>
7777777
</li>
<li>
8888888
</li>
<li>
999999999
</li>
</ol>
<div class="yui-carousel-nav">
<button id="next" class="yui-carousel-button yui-carousel-next"><span>next</span></button>
<button id="prev" class="yui-carousel-button yui-carousel-prev"><span>prev</span></button>
</div>
</div>
i use above but still navigation appear in above of items
you must use custom navigation buttons for solve this problem, follow this:
use below css in the stylesheed
.yui-carousel .yui-carousel-item-selected {
border: none;
}
.yui-skin-sam .yui-carousel-nav {
position: relative;
top: 0px;
right: 1px;
height: 1px;
background: none;
}
.yui-skin-sam .yui-carousel-button {
display: none;
}
.yui-carousel-nav ul {
display: none;
}
use a think like this for js function call:
(function () {
var carousel;
YAHOO.util.Event.onDOMReady(function (ev) {
var carousel = new YAHOO.widget.Carousel("container", {
isCircular: false,
numVisible: 3,
navigation: { prev: 'prevButton' , next: 'nextButton' }
});
carousel.set("selectedItem", 0);
carousel.render(); // get ready for rendering the widget
carousel.show(); // display the widget
});
})();
then for custom navigation use a div like this:
......
<li>
999999999
</li>
</ol>
<div>
<button id="prevButton"><</button>
<button id="nextButton">></button>
</div>
see here
http://developer.yahoo.com/yui/carousel/#cssref
i have understand it like this
{ prev: prev_id, next: nextId }

Categories

Resources