I have two seperate dropdowns, whose hover states can't be target by css based on the html markup. I tried to solve this by jQuery and I am halfway done. One problem still exists all the time and I am trying to solve this by days now.
If I hover the link of the second dropdown and moves the mouse really fast to the link of the first dropdown and then move the mouse immediately into the container of the displayed first dropdown, this dropdown menu disappears. It seems that my script removes the adding css classes in this case. This situation only appears with fast mouse movement but it drives me crazy. I am unable to figure out why this happens. I include a jsfiddle demo, where you can see the problem by yourself.
jQuery
jQuery(document).ready(function($) {
var $body = $('body'),
$tg_header = $('#main-header'),
$tg_top_menu = $('ul.nav'),
/*$tg_submenu_link = $('.tg-submenu__link'),*/
$tg_submenu_link_tg = $('.tg-submenu__link--tg'),
$tg_submenu_link_abteilungen = $('.tg-submenu__link--abteilungen'),
$tg_submenu = $('.tg-submenu'),
$tg_submenu_tg = $('.tg-submenu__tg'),
$tg_submenu_abteilungen = $('.tg-submenu__abteilungen'),
et_menu_hover_triggered = false;
/* General Hiding Function for first mega menu */
function tg_hide_tg() {
setTimeout( function () {
if ($tg_top_menu.find('.tg-submenu__link--tg:hover').length == 0 && $('.tg-submenu__tg:hover').length == 0) {
$body.removeClass('tg-submenu__tg--active')
};
}, 50);
}
/* General Hiding Function for second mega menu */
function tg_hide_abteilungen() {
setTimeout( function () {
if ($tg_top_menu.find('.tg-submenu__link--abteilungen:hover').length == 0 && $('.tg-submenu__abteilungen:hover').length == 0) {
$body.removeClass('tg-submenu__abteilungen--active')
};
}, 50);
}
/* Mouse Hover Mega Link 1 and Leave Link */
$tg_submenu_link_tg.mouseenter(function() {
$body.addClass('tg-submenu__tg--active');
}).mouseleave(function() {
tg_hide_tg();
});
/* Mouse Leave Mega Menu Container 1 */
$tg_submenu_tg.mouseleave(function () {
setTimeout(function () {
if ($('.tg-submenu__link--tg:hover').length == 0 && $('.tg-submenu__tg:hover').length == 0 ) {
$body.removeClass('tg-submenu__tg--active');
};
},50)
});
/* Mouse Hover Mega Link 2 and Leave Link */
$tg_submenu_link_abteilungen.mouseenter(function() {
$body.addClass('tg-submenu__abteilungen--active');
}).mouseleave(function() {
tg_hide_abteilungen();
})
/* Mouse Leave Mega Menu Container 2 */
$tg_submenu_abteilungen.mouseleave(function () {
setTimeout(function () {
if ($('.tg-submenu__link--abteilungen:hover').length == 0 && $('.tg-submenu__abteilungen:hover').length == 0 ) {
$body.removeClass('tg-submenu__abteilungen--active');
};
},50)
});
});
HTML-Markup
<body>
<header id="main-header">
<div class="container">
<div id="et-top-navigation">
<div class="tg-mainMenu__left">
<nav id="top-menu-nav">
<ul id="top-menu" class="nav">
<li id="menu-item-154" class="tg-submenu__link tg-submenu__link--tg menu-item">MEGA LINK 1</li>
<li id="menu-item-156" class="tg-submenu__link tg-submenu__link--abteilungen menu-item">MEGA LINK 2</li>
<li id="menu-item-166" class="menu-item menu-item">Normal Link 3</li>
</ul>
</nav>
</div><!-- TG-mainMenu__left-->
<div class="tg-mainMenu__right">
<nav id="top-menu-nav">
<ul id="top-menu" class="nav">
<li id="menu-item-154" class="menu-item menu-item">Normal Link 4</li>
<li id="menu-item-154" class="menu-item menu-item">Normal Link 5</li>
<li id="menu-item-154" class="menu-item menu-item">Normal Link 6</li>
</ul>
</nav>
</div> <!-- tg-mainMenu__right -->
</div> <!-- #et-top-navigation -->
<!-- TG Mega 1 -->
<div class="tg-submenu tg-submenu__tg">
<div class="container tg-submenu__content">
<h1>
MEGA MENU 1
</h1>
</div>
</div>
<!-- Abteilungen Mega -->
<div class="tg-submenu tg-submenu__abteilungen">
<div class="container tg-submenu__content">
<h1>
MEGA MENU 2
</h1>
</div>
</div>
</div> <!-- .container -->
</header>
</body>
My fiddle: https://jsfiddle.net/hfammzce/
I dont know why this is happening. But you can use jQuery .show() and .hide() instead of using add/remove class and opacity.
Here is the updated fiddle: https://jsfiddle.net/1dzyszdq/
/* General Hiding Function for first mega menu */
function tg_hide_tg() {
setTimeout( function () {
if ($tg_top_menu.find('.tg-submenu__link--tg:hover').length == 0 && $('.tg-submenu__tg:hover').length == 0) {
$(".tg-submenu__tg").hide();
};
}, 50);
}
/* Mouse Hover Mega Link 1 and Leave Link */
$tg_submenu_link_tg.mouseenter(function() {
$('.tg-submenu__tg').show();
}).mouseleave(function() {
tg_hide_tg();
});
Related
Can anyone help me out with a small responsive web project I'm currently doing?
I want to hide the menu nav bar when the user is on the top most part of the page, and only show it when the user starts scrolling down (on the mobile version), but have no idea how to, below are my code segments (mostly based on W3school template as I'm trying to learn web page making and it is the most reliable source I've found so far):
<!-- Navbar -->
<div class="w3-top">
<ul class="w3-navbar w3-sea-green w3-card-2 w3-left-align">
<li class="w3-hide-medium w3-hide-large w3-opennav w3-right">
<a class="w3-padding-large" href="javascript:void(0)" onclick="myFunction()" title="Toggle Navigation Menu"><i class="fa fa-bars"></i></a>
</li>
<li>HOME</li>
<li class="w3-hide-small">DOWNLOAD</li>
<li class="w3-hide-small">ABOUT</li>
<li class="w3-hide-small">CONTACT</li>
</ul>
</div>
<!-- Navbar on small screens -->
<div id="navDemo" class="w3-hide w3-hide-large w3-hide-medium w3-top" style="margin-top:46px">
<ul class="w3-navbar w3-left-align w3-sea-green">
<li><a class="w3-padding-large w3-hover-text-sea-green-invert" href="#download">DOWNLOAD</a></li>
<li><a class="w3-padding-large w3-hover-text-sea-green-invert" href="#about">ABOUT</a></li>
<li><a class="w3-padding-large w3-hover-text-sea-green-invert" href="#contact">CONTACT</a></li>
</ul>
</div>
<script>
// Used to toggle the menu on small screens when clicking on the menu button
function myFunction() {
var x = document.getElementById("navDemo");
if (x.className.indexOf("w3-show") == -1) {
x.className += " w3-show";
} else {
x.className = x.className.replace(" w3-show", "");
}
}
// When the user clicks anywhere outside of the modal, close it
var modal = document.getElementById('ticketModal');
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
<!--Header image-->
<div class="mySlides w3-display-container w3-center">
<img src="pics/header_img.png" style="width:100%; pointer-events:none;" draggable="false">
</div>
Am really appreciating any help, many thanks!
Always use:
.classList.add() // To add the class
.classList.remove() // To remove the class
This makes your code:
function myFunction() {
var x = document.getElementById("navDemo");
if (x.className.indexOf("w3-show") == -1) {
x.classList.add("w3-show");
} else {
x.classList.remove("w3-show");
}
}
And finally, please don't follow W3Schools and you end up like this.
function change(){
navbar=document.getElementsByClassName("w3-top")[0];
if(window.scrollTop>20){
//show
navbar.style.display="block";
}else{
//hide
navbar.style.display="none";
}}
window.onload=window.onscroll=change;
On page load or if the user scroll, check if the user scrolled down...
you have to detect when the user scroll or not and if not scroll add class hidden and if scroll remove class hidden.
$(window).scroll(function (){
var scroll = $(window).scrollTop();
if (scroll >=20) {
$('.w3-top').removeClass('hidden');
}
else {
$('.w3-top').addClass('hidden');
}
});
the css
.hidden {
display: none;
}
Made a Fiddle here:
https://jsfiddle.net/r94dq2e4/
I am using twitter bootstap version 3 with a slide in menu from the left when navbar toggle button is clicked.
This is the jQuery code I'm using:
// Nav
(function ($) {
'use strict';
// Toggle classes in body for syncing sliding animation with other elements
$('#bs-example-navbar-collapse-2')
.on('show.bs.collapse', function (e) {
$('body').addClass('menu-slider');
})
.on('shown.bs.collapse', function (e) {
$('body').addClass('in');
})
.on('hide.bs.collapse', function (e) {
$('body').removeClass('menu-slider');
})
.on('hidden.bs.collapse', function (e) {
$('body').removeClass('in');
});
})(jQuery);
This works well and on first click of the navbar toggle button, the menu slides in, when clicked again, the menu slides out. I would like to enhance this functionality in such a way that the menu slides out when the user clicks anywhere on the page except for the menu itself.
This is my HTML for the menu:
Toggle navigation
Menu
<div class="navbar-collapse collapse" id="bs-example-navbar-collapse-2">
<ul class="nav navbar-nav">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Treatments<b class="caret"></b></a>
<ul class="dropdown-menu">
<li>Menu Item</span></li>
</ul>
</li>
<li>About Us</li>
<li>Meet the team</li>
<li>See the results</li>
<li>Cost</li>
<li>Information</li>
</ul><!-- end navbar-nav -->
</div><!-- end navbar-collapse -->
</nav><!-- end navbar -->
I have started with the following jQuery code to achieve this. But I would need some help in where to go from here:
/* Nav click outside hide navbar */
$(document).click(function(e){
// Check if click was triggered on or within #menu_content
if( $(e.target).closest("#navbar2").length > 0 ) {
return false;
}
// Otherwise
// trigger your click function
$('body').removeClass('menu-slider');
$('body').removeClass('in');
});
Thank you
There are 3 things that you need to check in order to see if you should close the menu:
The element is not the nav itself (.nav)
The element is not the nav container (.navbar-cllapse)
The element is not a child-element of the nav (.parents('.nav'))
if (!$(e.target).hasClass('navbar-collapse') && !$(e.target).hasClass('nav') && $(e.target).parents('.nav').length == 0) {
$('#bs-example-navbar-collapse-2').removeClass('in');
}
You can try it in this fiddle:
https://jsfiddle.net/r94dq2e4/1/
I trying to hide my nav on scroll down and show on scroll up only when in mobile mode. I have a example that i found from another website that uses a script that does the same only i'm not really good in unraveling and adjusting it to my situation. You see it working when the browser size is small.
--> Example website
I have a navigation that has two versions: one inline when in large screen size and position is absolute and the second in mobile screen size with a hamburger icon the open the menu items under each other.
--> Fiddle
<header>
<nav>
<div class="mobile-nav">
<div class="nav-toggle"><i class="nav-icon"></i></div>
</div>
<ul class="left-nav">
<li class="home">Pixelation</li>
</ul>
<ul class="right-nav">
<li>Work</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
</header>
Part of the script of example website
hideShowMobileNav = function(setOldScroll) {
if (stateMap.scrollTop != stateMap.oldScrollTop && stateMap.scrollTop > 100) {
if (stateMap.scrollTop > stateMap.oldScrollTop) {
jqueryMap.$nav.addClass('hidden');
} else {
jqueryMap.$nav.removeClass('hidden');
}
}
if (setOldScroll) {
stateMap.oldScrollTop = stateMap.scrollTop;
}
};
You could use device detection
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) ) {
// Do something
} else {
// Do something else
}
or width() function
or some sort of css media query
I need help in automatically closing a toggle-nav menu on mobile. Right now it doesn't close when a menu is selected.
HTML:
<!-- fixed header -->
<header id="navbar-top">
<div class="pt_navbar">
<div class="container">
<div class="row">
<div class="col-lg-12">
<!-- start menu-->
<div id="main-nav">
<i class="fa fa-bars"></i> Miracle Trainer
<ul class="pt_nav nav">
<li class="active">
Welcome
</li>
<li>
Training Videos
</li>
<li>
Pricing
</li>
<li>
Contact
</li>
</ul>
</div>
<!-- end menu-->
</div>
</div>
</div>
</div>
</header>
JS:
I need a way to close the toggle-nav when a menu is selected.
$("body").on('click', '#toggle-nav', function(e){
e.preventDefault();
var nav_menu = $("#navbar-top .pt_navbar ul");
if( nav_menu.height() < 10 ){
nav_menu.addClass('open_menu');
}else{
nav_menu.removeClass('open_menu');
}
});
I am currently using this for a slide-out menu:
$('.slideout-menu-toggle, .select').on('click', function(event){
event.preventDefault();
// create menu variables
var slideoutMenu = $('.slideout-menu');
var slideoutMenuWidth = $('.slideout-menu').width();
// toggle open class
slideoutMenu.toggleClass("open");
// slide menu
if (slideoutMenu.hasClass("open")) {
slideoutMenu.animate({
right: "0px"
});
} else {
slideoutMenu.animate({
right: -slideoutMenuWidth
}, 400);
}
});
Some adjustments might work for you.
EDIT: with the above working code in mind, I think your first jQuery line should be like this:
$('#toggle-nav, .select').on('click', function(e){
and add the "select" class to your list items.
I have navigation:
<li class="sliding-element zobrazSubMenu">
AntivĂrusy
<div class="sub-content">Bla blabla</div>
</li>
<li class="sliding-element zobrazSubMenu">
Virusy
<div class="sub-content">Some content</div>
</li>
I need to show sub-content div if I hover on the <li> element, but if I leave mouse, I need add some timeout (1sec) to hide sub-content.
And if I hover first <li>, and second <li>, and again rist <li>, before timeout end (1sec), do not hide the first sub-content.
Live example what I want: http://www.designchemical.com/lab/jquery-mega-drop-down-menu-plugin/advanced-styling/ the black navigation hover.
Move mouse to "Vehicles" and then move mouse to "About us" and fast again "Vehicles". This is effect what I dont know.
I need this apply to my custom VERTICAL menu.
Assuming you use jQuery you can do it like this:
HTML
<li class="sliding-element zobrazSubMenu" onmouseenter="showSubContent(this)" onmouseleave="hideSubContent(this)">
AntivĂrusy
<div class="sub-content">Bla blabla</div>
</li>
<li class="sliding-element zobrazSubMenu" onmouseenter="showSubContent(this)" onmouseleave="hideSubContent(this)">
Virusy
<div class="sub-content">Some content</div>
</li>
Javascript
function showSubContent(sender) {
if (sender.timerHandle === undefined) {
$(sender).find(".sub-content").show();
} else {
clearTimeout(sender.timerHandle);
sender.timerHandle = undefined;
}
}
function hideSubContent(sender) {
sender.timerHandle = setTimeout(function () {
$(sender).find(".sub-content").hide();
sender.timerHandle = undefined;
}, 1000);
}
Working demo