Dropdown Menu Closes On Hover (Error) - javascript

Whhenever I hover over the menu it works fine. But, when I try to get to the submenu links and children, the menu closes
/*----------------------------------------------------
/* Dropdown menu
/* ------------------------------------------------- */
jQuery(document).ready(function($) {
function mtsDropdownMenu() {
var wWidth = $(window).width();
if (wWidth > 865) {
$('#navigation ul.sub-menu, #navigation ul.children').hide();
var timer;
var delay = 100;
$('#navigation li').hover(
function() {
var $this = $(this);
timer = setTimeout(function() {
$this.children('ul.sub-menu, ul.children').slideDown('fast');
}, delay);
},
function() {
$(this).children('ul.sub-menu, ul.children').hide();
clearTimeout(timer);
}
);
} else {
$('#navigation li').unbind('hover');
$('#navigation li.active > ul.sub-menu, #navigation li.active > ul.children').show();
}
}
mtsDropdownMenu();
$(window).resize(function() {
mtsDropdownMenu();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li id="menu-item-513" class="menu-item "><i class="fa fa-calculator"></i> OFFERTE AANVRAGEN
<ul class="sub-menu">
<li id="menu-item-1146" class="menu-item">Zonnepanelen installatie (België)
</li>
<li id="menu-item-1144" class="menu-item">Zonnepanelen reinigen (België)
</li>
<li id="menu-item-1145" class="menu-item">Zonnepanelen installatie (Nederland)
</li>
</ul>
</li>

The code you posted works just fine; here's a plnkr to prove it: https://plnkr.co/edit/IFaueUhKE3J1K9vY1NkQ?p=preview
(simply wrapped a <div id='navigation'><ul> round the top li).
If you still loose the hover over the child-elements, it's caused by something you're not showing in the original question. E.g. adding this css:
li.menu-item {
position: relative;
top: 50px;
left: 300px;
}
would make it difficult to reach the child items because you, briefly, lose the parent-hover while moving to the child.

Related

Active Navigation On Scroll anchor links

I've been trying to figure this out for hours. I currently have a fixed nav for my anchor website. I would like the menu link background color to change when scrolling through each section. Like this: https://codepen.io/dbilanoski/pen/LabpzG . When I scroll through each section I only see the hover background color not the active state color. If you have any tips or advice, please advise.
Thank you!
var navLink = $(".nav-link"),
topMenuHeight = navLink.outerHeight() + 15,
//All list items
menuItems = navLink.find("a"),
//Anchors corresponding to menu items
scrollItems = menuItems.map(function() {
var item = $($(this).attr("href"));
if (item.length) {
return item;
}
});
// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e) {
var href = $(this).attr("href")
offsetTop = href === "#" ? 0 : $(href).offset().top - topMenuHeight + 1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});
// Bind to scroll
$(window).scroll(function() {
// Get container scroll position
var fromTop = $(this).scrollTop() + topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function() {
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length - 1];
var id = cur && cur.length ? cur[0].id : "";
if (navLink !== id) {
navLink = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href='#" + id + "']").parent().addClass("active");
}
});
a {
color: inherit;
text-decoration: none;
}
a:hover {
color: #fa448c;
text-decoration: underline;
}
a:active {
background-color: #fa448c;
color: #fff;
}
li {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="menu">
<ul class="nav-list">
<li class="nav-item">
Home
</li>
<li class="nav-item">
Products
</li>
<li class="nav-item">
Featured
</li>
<li class="nav-item">
Best Sellers
</li>
<li class="nav-item">
Contact
</li>
</ul>
</div>
The trick of the codepen you've sent is that all sections have the same height. However, there's a more flexible way of doing that. Using this solution, you check for each section whether it's shown on the screen or not, and if it is, highlight its button in the navlist.

Change text color of a span with Javascript while hovering on seperated div

I have a menupoint and underneath it a seperate div / mega menu. I triggered the mega menu to show up via Javascript. When I am hovering over the mega menu, the desired span in the menu should get highlighted with another color and also the background color should change. You can see in the code how I tried to solve it (comments included). Can you please help me. I don´t know why I can´t trigger it via .getElementsByClassName!?
//Showing mega menu on hover over menu point
document.getElementById("menu-item-136").addEventListener("mouseover", mouseOver);
document.getElementById("menu-item-136").addEventListener("mouseout", mouseOut);
function mouseOver() {
document.getElementById("mega-menu").style.display = "block";
}
function mouseOut() {
document.getElementById("mega-menu").style.display = "none";
}
//Let mega menu stay visible when hovering over it
//Style menupoint when hovering over mega menu div (NOT WORKING)!
document.getElementById("mega-menu").addEventListener("mouseover", mouseOver);
document.getElementById("mega-menu").addEventListener("mouseout", mouseOut);
function mouseOver() {
document.getElementById("mega-menu").style.display = "block";
document.getElementsByClassName (".aux-menu-label").style.color = "yellow";
}
function mouseOut() {
document.getElementById("mega-menu").style.display = "none";
document.getElementsByClassName (".aux-menu-label").style.color = "";
}
.menu-item-136 {
background-color: grey;
height: 50px;
}
.menu-item-136:hover {
background-color:green;
}
.aux-menu-label {
color:blue;
}
.mega-menu-1 {
display: none;
background-color: green;
height: 200px;
}
<div>
<li id="menu-item-136" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-136 aux-menu-depth-0 aux-menu-root-2 aux-menu-item">
<a href="#" class="aux-item-content">
<span class="aux-menu-label"><i aria-hidden="true" class="services auxicon-list"></i> Leistungen</span>
<span class="aux-submenu-indicator"></span></a>
</div>
<div id="mega-menu" class="mega-menu-1">content</div>
Thanks for your help!
Your code is a bit messy but you are calling your class incorrectly:
This:
document.getElementsByClassName (".aux-menu-label")
Should be this:
document.getElementsByClassName ("aux-menu-label")
Additionally, when using getElementsByClassName you are provided with an array-like object with all elements that have the class you have specified.
With that in mind, you must run a loop to target elements with the styles you want to apply.
The below code is how we will target multiple labels and change them to yellow on hover:
var labels = document.getElementsByClassName("aux-menu-label");
for (var i = 0; i < labels.length; i++) {
labels[i].style.color = "yellow"
}
When you run the snippet below you will see I have used similar code to revert the color back to blue onmouseout.
Learn more about getElementsByClassName here.
//Including this to show you how to target CSS child elements as described in your comment
var childElement = document.querySelector('#menu-item-136 .aux-item-content');
childElement.style.backgroundColor = "white";
console.log(childElement);
//Showing mega menu on hover over menu point
document.getElementById("menu-item-136").addEventListener("mouseover", mouseOver);
document.getElementById("menu-item-136").addEventListener("mouseout", mouseOut);
function mouseOver() {
document.getElementById("mega-menu").style.display = "block";
}
function mouseOut() {
document.getElementById("mega-menu").style.display = "none";
}
//Let mega menu stay visible when hovering over it
//Style menupoint when hovering over mega menu div (NOT WORKING)!
document.getElementById("mega-menu").addEventListener("mouseover", mouseOver);
document.getElementById("mega-menu").addEventListener("mouseout", mouseOut);
function mouseOver() {
document.getElementById("mega-menu").style.display = "block";
var labels = document.getElementsByClassName("aux-menu-label");
for (var i = 0; i < labels.length; i++) {
labels[0].style.color = "yellow"
}
}
function mouseOut() {
document.getElementById("mega-menu").style.display = "none";
var labels = document.getElementsByClassName("aux-menu-label");
for (var i = 0; i < labels.length; i++) {
labels[i].style.color = "blue"
}
}
.menu-item-136 {
background-color: grey;
height: 50px;
}
.menu-item-136:hover {
background-color: green;
}
.aux-menu-label {
color: blue;
}
.mega-menu-1 {
display: none;
background-color: green;
height: 200px;
}
<div>
<li id="menu-item-136" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-136 aux-menu-depth-0 aux-menu-root-2 aux-menu-item">
<a href="#" class="aux-item-content">
<span class="aux-menu-label"><i aria-hidden="true" class="services auxicon-list"></i> Leistungen</span>
<span class="aux-submenu-indicator"></span></a>
</div>
<div id="mega-menu" class="mega-menu-1">content</div>
<div>
<li id="menu-item-136" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-136 aux-menu-depth-0 aux-menu-root-2 aux-menu-item">
<a href="#" class="aux-item-content">
<span class="aux-menu-label"><i aria-hidden="true" class="services auxicon-list"></i> Leistungen</span>
<span class="aux-submenu-indicator"></span></a>
</div>
<div id="mega-menu" class="mega-menu-1">content</div>
EDIT: I've included the following javascript to show you how to target child elements and apply CSS to them. The code below will target the child of #menu-item-136 and change its background color to white. Run the snippet to see.
var childElement = document.querySelector('#menu-item-136 .aux-item-content');
childElement.style.backgroundColor = "white";
console.log(childElement);
In your code
If we add some margin to megamenu wrapper This will be not working
and menu close when pointer out from menu item.
I have fixed that isseue
Its Looks like with WordPress menu. Please check below example and its will be helpful to use multiple mega-menues You need to map megamenu data id with menu class item.
codepen example
[].forEach.call(document.querySelectorAll('nav > ul > li'), function (link) {
link.addEventListener('mouseover', coloringHandler);
link.addEventListener('mouseout', decoloringHandler);
});
[].forEach.call(document.querySelectorAll('.megamenu'), function (menu) {
menu.addEventListener('mouseover', megamenuHover );
});
var state = false;
function coloringHandler(){
state = false;
hideAllMegamenu();
// add class to current hover element
this.classList.add('active');
var Classes = this.classList; // getting all class list
Classes.forEach(name => {
var megaMenu = document.querySelectorAll('[data-id="'+name+'"]'); // check if have any mached elements with class name
if(megaMenu.length == 1 ){
megaMenu[0].classList.add('active');
state = true;
megaMenu[0].addEventListener('mouseover', megamenuHover );
megaMenu[0].addEventListener('mouseout', megamenuHoverOut );
return;
}
});
}
function decoloringHandler(){
if( state == false ){
this.classList.remove('active');
hideAllMegamenu();
}
}
function hideAllMegamenu(){
// change elemets as you want
[].forEach.call(document.querySelectorAll('nav > ul > li'), function (li) {
li.classList.remove("active");
});
// .megamenu is common class
[].forEach.call(document.querySelectorAll('.megamenu'), function (menues) {
menues.classList.remove('active');
})
}
function megamenuHover() {
this.classList.add('in-hover');
}
function megamenuHoverOut() {
hideAllMegamenu();
}
nav ul{
display:flex;
list-style:none;
}
li{
margin:0px 10px;
}
a{
background:green;
display:block;
color:white;
padding:10px 20px;
}
ul li.active a{
background:red;
}
.megamenu{
background: red;
height:200px;
pointer-events: none;
opacity:0;
position:absolute;
width:100%;
padding:20px;
color:#fff;
transition:all .5s ease;
transform:translateY(50px);
}
.megamenu.active{
opacity:1;
pointer-events: all;
transform:translateY(0px);
}
<h1>Hover over the menu Items</h1>
<nav>
<ul>
<li class="menu-item-136">
<span>Home</span>
</li>
<li class="menu-item-137">
<span>Contact us</span>
</li>
<li class="menu-item-138">
<span>Danushka</span>
</li>
<li class="menu-item-139">
<span>About us</span>
</li>
</ul>
</nav>
<div class="megamenu" data-id="menu-item-137">
Lorem ipsum dolor sit amet consectetur adipisicing elit.
</div>
<div class="megamenu" data-id="menu-item-138">
Danushka Megamenu... Add data id for mapping
</div>

Close jQuery menu on mouseLeave

I am building a small drop-down container which appears when You hover on top of a menu item. When I hover on top of the menu item (e.g. Tools) the dropdown appears, I can move my mouse inside, but when the cursor leaves the dropdown menu, it does not go away. How am I able to achieve this?
I only managed to make it dissapear when you click somewhere outside of it.
Here is a Fiddle.
var dropdown = $('.nav-dropdown');
dropdown.hide();
$('#dropdownToggle').hover(function(e) {
e.preventDefault();
dropdown.show(200);
dropdown.addClass('active');
$(window).click(function() {
dropdown.slideUp();
});
e.stopPropagation();
});
SOLUTION by anima_incognita:
var dropdown = $('.nav-dropdown');
dropdown.hide();
$('#dropdownToggle').hover(function(e) {
e.preventDefault();
dropdown.show(200);
dropdown.addClass('active');
$(window).click(function() {
dropdown.slideUp();
});
$(".nav-dropdown").on('mouseleave',function(){
dropdown.slideUp();
});
e.stopPropagation();
});
here is edit in your code worked fine with me...added methods
var dropdown = $('.nav-dropdown');
dropdown.hide();
$('#dropdownToggle').mouseenter(function(e) {
e.preventDefault();
dropdown.show(200);
dropdown.addClass('active');
$(window).click(function() {
dropdown.slideUp();
});
$('#dropdownToggle').mouseleave(function(e) {
dropdown.slideUp();
});
e.stopPropagation();
});
Add this to end of your code:
$(".nav-dropdown").on('mouseleave',function(){
dropdown.hide();
});
Update your JS:
var dropdown = $('.nav-dropdown');
dropdown.hide();
$('#dropdownToggle').hover(function(e) {
e.preventDefault();
dropdown.show(200);
dropdown.addClass('active');
$(window).click(function() {
dropdown.slideUp();
});
e.stopPropagation();
});
$(".nav-dropdown").on('mouseleave', function() {
dropdown.slideUp('fast');
});
.nav-list {
.nav-list-item {
float: left;
list-style: none;
padding: 2rem;
background: tomato;
font-family: 'Helvetica', 'Arial', sans-serif;
a {
text-decoration: none;
text-transform: uppercase;
font-weight: bold;
color: #fff;
}
.nav-dropdown {
position: absolute;
background: turquoise;
padding: 2rem;
li {
margin-bottom: 2rem;
}
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav-list">
<li class="nav-list-item">
Services
</li>
<li class="nav-list-item dropdown-wrapper">
<a href="#" id="dropdownToggle" class="nav-link tools">Tools
</a>
<!-- dropdown -->
<ul class="nav-dropdown active" style="display: block;">
<li class="nav-dropdown-item">
Buyer Cost Sheet
</li>
<li class="nav-dropdown-item">
Seller Net Sheet
</li>
<li class="nav-dropdown-item">
Mortage Calculator
</li>
<li class="nav-dropdown-item">
Title Fees
</li>
<li class="nav-dropdown-item">
Refi Calculator
</li>
<li class="nav-dropdown-item">
Real Estate Forms
</li>
</ul>
</li>
<li class="nav-list-item">
Buyers & Sellers
</li>
</ul>
As you are using the hover function, the hover function specifies two function to trigger mouseenter and mouseleave event
You have defined only the mouseenter function and not defined the mouseleave function. So below is the updated JS code:
$('#dropdownToggle').hover(function(e) {
e.preventDefault();
dropdown.show(200);
dropdown.addClass('active');
e.stopPropagation();
}, function(e){
e.preventDefault();
dropdown.slideUp();;
dropdown.removeClass('active');
});

Use of this in javascript/Jquery

I have an anchor tag as below :
<a href='#' class='control_next_photo'>></a>
I have set an event on click of the above anchor as follows:
$('a.control_prev_photo').click(function () {
moveLeft();
return false;
});
Below is the moveLeft function.
function moveLeft() {
$('#post-text-slider ul').animate({
left: + slideWidth
}, 200, function () {
$('#post-text-slider ul li:last-child').prependTo('#post-text-slider ul');
$('#post-text-slider ul').css('left', '');
});
};
Now my concerns is that the above is working perfectly when there is only one "post-text-slider" DIV inside which we have an anchor tag. when a user is clicking on the anchor tag the moveLeft() is getting called which in turn moving the slide to left.
But actually, I have several "post-text-slider" DIVs inside which have their own anchor tag. Now in that case if a user clicks on the anchor tag, it will trigger the moveLeft() for all the "post-text-slider" which is not desirable.
Can someone please assist me with the solution for this.
If I figured out correctly your problem I suggest you:
convert post-text-slider from ID to class
use $(e.target).closest('div.post-text-slider') to get the current div
pass to moveLeft as argument the div element
var slideWidth = 100;
function oldMoveLeft() {
$('.post-text-slider ul').animate({
left: + slideWidth
}, 200, function () {
$('.post-text-slider ul li:last-child').prependTo('.post-text-slider ul');
$('.post-text-slider ul').css('left', '');
});
}
function moveLeft(element) {
var ulEle = element.find('ul');
ulEle.animate({
left: + slideWidth
}, 200, function () {
ulEle.find('li:last-child').prependTo(ulEle);
ulEle.css('left', '');
});
}
$(function () {
$('a.control_prev_photo').click(function (e) {
e.preventDefault();
moveLeft($(e.target).closest('div.post-text-slider'));
});
// old one
$('a.old').click(function () {
oldMoveLeft();
return false;
});
});
.post-text-slider {
width: 100%;
}
.control_prev_photo {
appearance: button;
-moz-appearance: button;
-webkit-appearance: button;
text-decoration: none; font: menu; color: ButtonText;
display: inline-block; padding: 2px 8px;
}
ul {
position: relative;
}
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<div class="post-text-slider">
<a class="control_prev_photo">Click Me</a>
<a class="control_prev_photo old">Old Click Me behoviour</a>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
<div class="post-text-slider">
<a class="control_prev_photo">Click Me</a>
<a class="control_prev_photo old">Old Click Me behoviour</a>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
<div class="post-text-slider">
<a class="control_prev_photo">Click Me</a>
<a class="control_prev_photo old">Old Click Me behoviour</a>
<ul>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>

How to activate menu tab after refreshing

How can I activate a menu tab after refreshing?
Here are my code
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<style>
.menu{width: 600px; height: 25; font-size: 18px;}
.menu li{list-style: none; float: left; margin-right: 4px; padding: 5px;}
.menu li:hover, .menu li.active {
background-color: #f90;
}
</style>
</head>
<body>
<ul class="menu">
<li><a href='#'>One</a></li>
<li><a href='#'>Two</a></li>
<li><a href='#'>Three</a></li>
<li><a href='#'>Four</a></li>
</ul>
<script type="text/javascript">
var make_button_active = function()
{
//Get item siblings
var siblings =($(this).siblings());
//Remove active class on all buttons
siblings.each(function (index)
{
$(this).removeClass('active');
}
)
//Add the clicked button class
$(this).addClass('active');
}
//Attach events to menu
$(document).ready(
function()
{
$(".menu li").click(make_button_active);
}
)
</script>
Can anyone tell me How to resolve this issue ?
Just like #Johan said, store your last active tab in a localStorage or cookie. Since there is no noticeable difference in performance between the two. I suggest you use localStorage because it's much easier to use. Like this:
function make_button_active(tab) {
//Get item siblings
var siblings = tab.siblings();
//Remove active class on all buttons
siblings.each(function(){
$(this).removeClass('active');
})
//Add the clicked button class
tab.addClass('active');
}
//Attach events to menu
$(document).ready(function(){
if(localStorage){
var ind = localStorage['tab']
make_button_active($('.menu li').eq(ind));
}
$(".menu li").click(function () {
if(localStorage){
localStorage['tab'] = $(this).index();
}
make_button_active($(this));
});
});
Check out this fiddle.

Categories