Displaying a dropdown menu on hover and replacing CSS classes - javascript

Two elements that needs to be manipulated with JS:
<li class="navTab myFirstTab Popup PopupControl PopupOpen PopupContainerControl">
For the above element:
I want OnMouseHover to replace the class value:
PopupClose with PopupOpen
<div class="Menu JsOnly tabMenu myFirstTabLinks" id="XenForoUniq0" style="display: block; visibility: visible; top: 96px; left: 960.5px;">
At the same time, the above element style attribute to change its value from: display: none; to display: block;
Sample of HTML structure:
<ul class="publicTabs navLeft">
<li class="navTab forums selected">
Home
</li>
<li class="navTab myFirstTab Popup PopupControl PopupClosed PopupContainerControl">
On hover I should have a DropDown
</li>
<li class="navTab mySecondTab Popup PopupControl PopupClosed PopupContainerControl uix_rightMost">
On hover I should have a DropDown​2
</li>
<!-- members -->
<!-- extra tabs: end -->
<!-- responsive popup -->
<li class="navTab navigationHiddenTabs navTab--j justIcon Popup PopupControl PopupClosed PopupContainerControl" style="display: none;">
<a rel="Menu" class="navLink NoPopupGadget uix_dropdownDesktopMenu"><i class="uix_icon uix_icon-navOverflow"></i><span class="uix_hide menuIcon">ham</span></a>
</li>
</ul>
<!-- START DropDown-->
<div class="Menu JsOnly tabMenu myFirstTabLinks" id="XenForoUniq0" style="display: none; visibility: visible; top: 96px; left: 960.5px;">
<div class="primaryContent menuHeader">
<h3>My First drop down menu title</h3>
</div>
<ul class="secondaryContent blockLinksList">
<li>item1</li>
<li>item2</li>
</ul>
</div>
<div class="Menu JsOnly tabMenu mySecondTabLinks" id="XenForoUniq1" style="display: none; visibility: visible; top: 76px; left: 879.5px;">
<div class="primaryContent menuHeader">
<h3>My Second drop down menu title</h3>
</div>
<ul class="secondaryContent blockLinksList">
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
<!-- FINISH DropDown -->

Add data-target attributes to your tablinks div.. similar to below
<li class="navTab myFirstTab Popup PopupControl PopupClosed PopupContainerControl" data-target="myFirstTabLinks">
<li class="navTab mySecondTab Popup PopupControl PopupClosed PopupContainerControl" data-target="mySecondTabLinks">
Now
$('.navTab.Popup').on('mouseenter', function() {
$(this).removeClass('PopupClosed').addClass('PopupOpen');
var cls = $(this).data('target'); // fetch which class to target.
$('.Menu.' + cls).css('display','block'); // will make display block
}). on('mouseleave', function() {
$(this).addClass('PopupClosed').removeClass('PopupOpen');
var cls = $(this).data('target'); // fetch which class to target.
$('.Menu.' + cls).css('display','none'); // will make display none
});

Related

How to make it so that when you click on one of the menu items, the other changes color?

How to make one of the li circles in .sidebar-nav change the background color to white when you click on one of the li in the .sidebar-menu, by adding the .actived class to it? Moreover, when one of the li in the .sidebar-menu is clicked, the circle from the .sidebar-nav should change color in accordance with the element that was clicked. For example, they clicked on the "Business card site" and the first circle lights up, clicked on the "Internet store" and the third circle lights up.
Site ct03638.tmweb.ru
Code jsfiddle.net/pjzs9uxw/
.actived {
background-color: #fff;
transition: 0.3s;
}
<section class="services" id="services">
<div class="wrapper">
<div class="content">
<div class="sidebar">
<h3>Наши услуги</h3>
<ul class="sidebar-menu">
<li id="business-card">Сайт-визитка</li>
<li id="landing">Landing page</li>
<li id="market">Интернет-магазин</li>
<li id="corp">Корпоративный сайт</li>
<li id="bitrix">1C Битрикс</li>
<li id="advertising">Контекстная реклама</li>
<li id="seo">SEO оптимизация</li>
<li id="promotion">Продвижение в соц. сетях</li>
<li id="marketing">Контент-маркетинг</li>
</ul>
<ul class="sidebar-nav">
<li class="business-card"></li>
<li class="landing"></li>
<li class="market"></li>
<li class="corp"></li>
<li class="bitrix"></li>
<li class="advertising"></li>
<li class="seo"></li>
<li class="promotion"></li>
<li class="marketing"></li>
</ul>
</div>
</div>
</div>
</section>
You can use index() of the li which is clicked then using that addClass to same li in your sidebar-nav ul.
Demo Code :
$('.sidebar-menu li a').on('click', function(e) {
e.preventDefault()
var index_ = $(this).closest("li").index() //get index
$('.sidebar-nav li').removeClass('actived');//remove from other
$(".sidebar-nav li:eq(" + index_ + ")").addClass('actived'); //add class where index is same
});
.actived {
background-color: red;
transition: 0.3s;
}
.sidebar-nav li {
width: 7px;
height: 7px;
border: 1px solid black;
border-radius: 50px;
margin-right: 5px;
cursor: pointer;
}
.sidebar-nav {
list-style: none;
display: flex;
justify-content: flex-start;
margin-left: 120px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<section class="services" id="services">
<div class="wrapper">
<div class="content">
<div class="sidebar">
<h3>Наши услуги</h3>
<ul class="sidebar-menu">
<li id="business-card">Сайт-визитка</li>
<li id="landing">Landing page</li>
<li id="market">Интернет-магазин</li>
<li id="corp">Корпоративный сайт</li>
<li id="bitrix">1C Битрикс</li>
<li id="advertising">Контекстная реклама</li>
<li id="seo">SEO оптимизация</li>
<li id="promotion">Продвижение в соц. сетях</li>
<li id="marketing">Контент-маркетинг</li>
</ul>
<ul class="sidebar-nav">
<li class="business-card"></li>
<li class="landing"></li>
<li class="market"></li>
<li class="corp"></li>
<li class="bitrix"></li>
<li class="advertising"></li>
<li class="seo"></li>
<li class="promotion"></li>
<li class="marketing"></li>
</ul>
</div>
</div>
</div>
</section>
Add click event listener on sidebar-menu ul element and capture the index of clicked li element, then get the circle element of same index and add active class on it and remove the active class from previous highlighted element.
const menuEle = document.querySelector("#side-menu");
let higlightedIndex = -1;
menuEle.addEventListener("click", (e) => {
const listItem = e.target.closest("li");
if (listItem) {
const index = [...menuEle.children].indexOf(listItem);
const list = document.querySelector("#sidebar-nav").children;
if (higlightedIndex >= 0) {
list[higlightedIndex].classList.remove("active");
}
list[index].classList.add("active");
higlightedIndex = index;
}
});
.active {
background-color: #FAE93E;
}
.circle {
width: 20px;
height: 20px;
border: 1px solid black;
border-radius: 50%;
display: inline-block;
}
<section class="services" id="services">
<div class="wrapper">
<div class="content">
<div class="sidebar">
<h3>Наши услуги</h3>
<ul class="sidebar-menu" id="side-menu">
<li id="business-card">Сайт-визитка</li>
<li id="landing">Landing page</li>
<li id="market">Интернет-магазин</li>
<li id="corp">Корпоративный сайт</li>
<li id="bitrix">1C Битрикс</li>
<li id="advertising">Контекстная реклама</li>
<li id="seo">SEO оптимизация</li>
<li id="promotion">Продвижение в соц. сетях</li>
<li id="marketing">Контент-маркетинг</li>
</ul>
<div id="sidebar-nav">
<span class="business-card circle"></span>
<span class="landing circle"></span>
<span class="market circle"></span>
<span class="corp circle"></span>
<span class="bitrix circle"></span>
<span class="advertising circle"></span>
<span class="seo circle"></span>
<span class="promotion circle"></span>
<span class="marketing circle"></span>
</div>
</div>
</div>
</div>
</section>
On the click function of your button, try adding a line that sets a class or an attribute to the parent menu element related to this current item. This way you can apply different styles according to the current menu item to the whole menu.

weird behaivior of a js function to remove and add a class in mobile while the struncutre is basiaclly the same

Basically, I want on the click event to remove the class active form the current element and move it the clicked one. I wrote the following code and in the desktop mode it work just fine but in the mobile version it doesn't remove the class from the "old active" element BUT if I click on the already active element the behaviour of my function goes back to normal.
HTML
<header>
<!-- the ul in the is visible untill 1200px, after that the "mobile-mene" make visibile a hamburger icon and the "menu" is invisible untill the hamburger is clicked -->
<nav>
<a href="#home">
<span class="logo">
Ernesto Dovizioso
</span>
</a>
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
<div class="mobile-menu">
<i class="fas fa-bars"></i>
</div>
</nav>
<!-- this is invisible untill the hb menu il clicked -->
<div class="menu">
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
</div>
</header>
JS
const ul = document.querySelectorAll("header ul li");
ul.forEach(li => {
li.addEventListener("click", activeLiChange);
});
function activeLiChange(){
let activeLi = document.querySelector("li.active");
console.log(this.innerHTML);
console.log(activeLi.innerHTML);
if(!this.isEqualNode(activeLi)){
this.classList.add("active");
activeLi.classList.remove("active");
}
}
The reason it isn't working on mobile is because you are using querySelector which only returns the first instance of .active which is in your non-mobile menu. You'll need to use querySelectorAll('li.active') and iterate over the resulting NodeList.
Using your code as is here is a fix:
const ul = document.querySelectorAll("header ul li");
ul.forEach(li => {
li.addEventListener("click", activeLiChange);
});
function activeLiChange(){
const activeLi = document.querySelectorAll("li.active");
activeLi.forEach(li => {
if(!this.isEqualNode(li)){
this.classList.add("active");
li.classList.remove("active")
}
});
}
.active {
color: tomato;
}
<header>
<nav>
<a href="#home">
<span class="logo">
Ernesto Dovizioso
</span>
</a>
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
<div class="mobile-menu">
<i class="fas fa-bars"></i>
</div>
</nav>
<!-- this is invisible untill the hb menu il clicked -->
<div class="menu">
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
</div>
</header>
But you can simplify this by attaching the listener to each ul element instead of every li. Then in your activeLiChange() function use target (the li) and currentTarget (the ul) to address the relevant menu list.
const ul = document.querySelectorAll("header ul");
ul.forEach(list => {
list.addEventListener("click", activeLiChange);
});
function activeLiChange(e){
const activeLi = e.currentTarget.querySelector("li.active");
if(!e.target.isEqualNode(activeLi)){
e.target.classList.add("active");
activeLi.classList.remove("active");
}
}
.active {
color: tomato;
}
<header>
<nav>
<a href="#home">
<span class="logo">
Ernesto Dovizioso
</span>
</a>
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
<div class="mobile-menu">
<i class="fas fa-bars"></i>
</div>
</nav>
<!-- this is invisible untill the hb menu il clicked -->
<div class="menu">
<ul>
<li class="active">home</li>
<li>chi sono</li>
<li>servizi</li>
<li>galleria</li>
<li>contatti</li>
</ul>
</div>
</header>

Sub menu on scrollable parent using HTML and CSS

I am programming this on rails but the problem is in html+css+javascript.
<ul>
<li>Menu1
<ul style="overflow: hidden auto; height: 400px; display: none;">
<li class="sub-menu">
<a href="#">
<div>submenu1</div>
</a>
<ul style="left: 258px; height: 400px; display: none;">
<li>
<a href="#">
<div>Subsubmenu1</div>
</a>
</li>
<li class="line"></li>
<li>
<a href="#">
<div>Subsubmenu2</div>
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
I have this long list of submenus so i want it scrollable.
As soon as i add overflow to the sub menu list the Sub Sub menus stop being displayed. I tried checking for javascript errors without success.

how to make nested list in slide panel?

Can you please tell me how to make a nested list in slide panel in jQuery?
I am able to make a slide panel, but I want to make nested list in left panel in jQuery.
http://jsfiddle.net/qUMbC/31/
can we make nested list in slide panel ?
<div data-role="page" class="jqm-demos" data-quicklinks="true">
<div data-role="header">
<h1>External panels</h1>
</div>
<div role="main" class="ui-content jqm-content jqm-fullwidth"> Open External Panel
</div>
</div>
<div data-role="panel" id="externalpanel" data-position="left" data-display="reveal" data-theme="a">
<h2>Menu</h2>
<ul data-role="listview" style="padding-right: 8px">
<li data-icon="false"><a href="#" class='sub1'>Submenu 1</a>
</li>
<li data-icon="false">Submenu 2
</li>
</ul>
<!-- submenu -->
</div>
Assuming you want the inner list to remain hidden until its parent is clicked, something like this might give you an idea:
HTML:
<ul id="myList" data-role="listview" style="padding-right: 8px">
<li data-icon="false"><a href="#" class='sub1'>Submenu1</a>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</li>
<li data-icon="false">Submenu 2
</li>
</ul>
CSS:
#myList ul {
display: none;
}
JavaScript:
$('#myList > li').click(function() {
var subList = $(this).children('ul');
if (subList.is(":hidden"))
subList.slideDown(200);
else
subList.slideUp(200);
});
JSFiddle demo

jQuery - delay with stop functions

Consider the following navigation layout
primary nav
secondary nav
sub nav (shown only on rollover
of primary or secondary nav
I'm needing for there to be a delay in the fadeOut call long enough for a user to get their mouse from the primary nav to the subnav and once over the subnav I need the hover fadeOut cancelled. Repeating the idea when hovering over the secondary nav item. (I know how to add the delay but not how to cancel the hover)
TIA
http://jsfiddle.net/Wm6Gp/
<div class="primary">
<ul class="primary common">
<li class="primary category" rel="politics">
POLITICS
</li>
</ul>
</div>
<div class="secondary">
<ul class="secondary common">
<li class="secondary category" rel="news">
NEWS
</li>
</ul>
</div>
<div style="display: block; height: 20px; width: 100px; overflow: hidden;">
<div id="politics" class="sub" style="display: none;">
<ul class="sub common">
<li class="sub">
POLITICS SUBNAV
</li>
</ul>
</div>
<div id="news" class="sub" style="display: none;">
<ul class="sub common">
<li class="sub">
NEWS SUBNAV
</li>
</ul>
</div>
</div>
$('.category').hover(
function() {
var subnav = $(this).attr('rel');
$('#' + subnav).fadeIn('slow');
}, function() {
var subnav = $(this).attr('rel');
$('#' + subnav).fadeOut('slow');
});
Try jQuery Hover Intent plugin - http://cherne.net/brian/resources/jquery.hoverIntent.html

Categories

Resources