Javascript navigation, hover show, unhover hide with timeout, how? - javascript

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

Related

submenu in another element hides after moving the mouse out

I've made a sub menu list that show/hide with jquery when user hover on li list, each li shows a separate element.
Now i'm facing a problem with the jQuery code that when mouseleave, it hide the element and can't detect the hover event over this element.
The thing is, I can make it hide when switching to another list menu item and getting out of the element block. but I need it to keep showing the submenu in case the mouse is over it.
here's the code:
$(".left-nav-list-view nav ul li").mouseenter(function () {
clearMenuFlyout();
if ($(this).data('has-submenu')) {
var submenu_id = $(this).children('a').data('menu-id');
$(".flyOut-nav-container").append($("[id=" + submenu_id + "]")).position({
my: "left+1 top+0",
at: "right top",
of: this
});
}
}).on("mouseleave", function () {
});
function clearMenuFlyout(){
$(".flyout-temp-container").append($(".flyOut-nav-container").children());
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="side-nav-container flex-fixed">
<nav class="left-nav-view collapsed" role="navigation">
<div class="app-logo">
<div class="burger-menu">
<span class="burger-menu-icon"></span>
</div>
</div>
<div class="left-nav-list-view">
<nav>
<ul>
<li><span>Dashboard</span></li>
<li id="AccountingMenu" data-has-submenu="true"><a data-menu-id="AccountingMenuItems" href="#"><span>Accounting</span><i class="list-in fa fa-chevron-right"></i></a></li>
<li id="InventoryMenu" data-has-submenu="true"><a data-menu-id="InventoryMenuItems" href="#"><span>Inventory</span><i class="list-in fa fa-chevron-right"></i></a></li>
</ul>
</nav>
</div>
</nav>
</div>
basically clearFlyout function takes an already existent menu element and throw it to another div. .flyout-temp-container is hidden by default

Can't target two different dropdowns properly by jQuery

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();
});

Stop slide in javascript

I used this parallax slider http://codepen.io/suez/pen/ByvKXE in my project.
Then I added a hover menu on the top of the page.
<ul class="menu">
<li class="list-menu fa-home"></li>
<li class="list-menu fa-suitcase"></li>
<li class="list-menu fa-flask"></li>
<li class="list-menu fa-user"></li>
<li class="list-menu fa-contact"></li>
</ul>
I would like to stop parallax slider when I put my mouse on the menu to click on the buttons.
How could I do that ?
Thanks for answer.
Have a look at http://codepen.io/anon/pen/YwGjNd. I have made following changes.
stopAutoSlide : variable to allow or block autoslide
mouseenter, mouseleave: events to change stopaAutoSlide state
if (!stopAutoSlide): to change current slide only if stopAutoSlide is false.
I hope this helps.
$(document).on("mouseenter", ".slider-pagi", function() {
stopAutoSlide = true;
});
$(document).on("mouseleave", ".slider-pagi", function() {
stopAutoSlide = false;
});

Change max height element after it being clicked

I'm writting a dropdown menu and I wanted to have the dropdown being controlled by javascript.
My dropdown has the sub menu hidden of sight max-height: 0px; and when the correspondent anchor tag is clicked, I change its max-height parameter to 400px, using the following function:
function drop_down(name) {
document.getElementById(name).style.maxHeight = "400px";
}
So far so good. The problem is that the element's max-height, stays at 400px and the sub menu does not hide. So I thought that I should target the click of the mouse and when this happens check if there is any element with 400px and change it back to 0.
$('html').click(function() {
var max_h = document.getElementsByClassName("nav_content");
var i;
for(i = 0 ; i < max_h.length ; i++)
{
if(max_h[i].style.maxHeight == "400px")
{
max_h[i].style.maxHeight = "0px";
}
}
});
What happens is that this function tracks every click, even the one used to display the sub menu. So my question is: is there a way to only activate the second function after I clicked my sub-menu? Because I always want the click that comes after the menu is displayed to close the sub menu.
HTML:
<body>
<div class="nav_container">
<nav class="nav_main">
<div class="logo">
<a href="#">
<img src="../majo.png" alt="logo">
</a>
</div>
<ul class="nav" id="nav">
<li>
Home
</li>
<li>
Consultas
<div id="nav_consul" class="nav_content">
<div class="nav_sub">
<ul>
<li>
Informação Dia a Dia
</li>
<li>
Totais Mensais
</li>
<li>
Tarifário Atual da Rede
</li>
<li>
Data específica
</li>
<li>
Atividade do Sistema
</li>
<li>
Coimas
</li>
</ul>
</div>
</div>
</li>
<li>
Simulações
<div id="nav_simul" class="nav_content">
<div class="nav_sub">
<ul>
<li>
Criar tarifa Simples
</li>
<li>
Criar tarifa Complexa
</li>
<li>
Simular com Nova Tarifa
</li>
</ul>
</div>
</div>
</li>
<li>
Preferências
<div id="nav_prefs" class="nav_content">
<div class="nav_sub">
<ul>
<li>
Lista de acessos
</li>
<li>
Alterar Password
</li>
<li>
Alterar Dados de Conta
</li>
</ul>
</div>
</div>
</li>
<li>
Log Out
</li>
</ul>
</nav>
</div>
<div id="content_main">
</div>
<footer></footer>
<script src="../js/jQuery.js"></script>
<script src="../js/user_menu.js"></script>
<script src="../js/user_nav.js"></script>
<script src="../js/user_clear_sub_menu.js"></script>
</body>
Here is an easy solution:
Create the following CSS-Styles:
.nav_content.visible {
max-height: 400px;
}
.nav_content.invisible {
max-height: 0px;
}
Set the overflow property for your nav_content to hidden:
.nav_content{
overflow: hidden;
}
Now add the class invisible to your submenus, if you want them to be invisible by default (you can do this manually in the markup or by js code):
Manually e.g.:
<div id="nav_prefs" class="nav_content invisible">
or by code (after the elements have been loaded):
$(".nav_content").addClass("invisible);
Now, if you just need to adjust your drop_down function to toggle the element's invisible/visible class:
function drop_down(dropdownID){
$('#'+dropdownID).toggleClass("visible invisible");
}
UPDATE: To make all visible submenus disappear when clicked elsewhere use this piece of code, when the window is loaded:
$(document).on('click', function (e) {
if (!$(e.target).is('.nav_item') && !$(".nav_item").has(e.target).length !== 0) {
$('.nav_content.visible').toggleClass("visible invisible");
}
});
If you only want to have one submenu visible at a time, you can use this version of your drop_down function:
function drop_down(dropdownID) {
$('.nav_content.visible').toggleClass("visible invisible");
$('#' + dropdownID).toggleClass("visible invisible");
}
A working fiddle can be found here
EDIT: Since you used jQuery in your original code, I assumed the answer can use jQuery too
You'll want to create a click handler on your document, then check the target of the click. If the target of the click has a certain class, use the menu behavior. If not, or if it's a sub-menu, close the menu.
Here's a question with multiple examples:
How do I close menu on click and when the user clicks away?
Also, I'd recommend not using max-height to hide and show. Since you're using jquery already, you could just use hide() and show().
One more thing: since you're using jquery already, you don't need to use these calls: document.getElementById(name). You can do a $("#yourId") or for document.getElementsByClassName("nav_content"); you can use $(".your-class")
It looks like you attached click event to entire document. I think you need to change only $('html').click(function() { to something like $('sub-menu-selector').click(function() { to
only activate the second function after I clicked my sub-menu
Aside to that, since it's only piece of jQuery and if you're not using it elsewhere, I would replace this with addEventListener and attachEvent, but maybe that's just me :)
In that case you can use jQuery.not() method to exclude the dropdown menu from your jQuery selection, here's what you need :
$('html').not(document.getElementsByClassName("nav_container")[0]).click(function() {
//As you can pass an element to it
You can also use the :not in your first selector like this:
$('html:not(div.nav_container))

jQuery: Delay showing of a dropdown menu content

I have built a dropdown menu that works fine. It goes like this:
Main menu items are in horizontal bar, then
When hover on any item, big dropdown box (with submenu links) is shown.
And here is my code for this:
HTML:
<!-- Based on Bootstrap -->
<div class="navbar navbar-inverse">
<div class="nav-collapse collapse">
<ul class="nav">
<li>First item
<div id="about-horizontal-submenu" class="horizontal-submenu">
<div class="submenu-container span3">
<ul>
<li>Links</li>
<li>Links</li>
</ul>
</div>
<!-- and 4x similar div (to have 12 cols) -->
</div>
</li>
<li>Dropdown
<div id="about-horizontal-submenu" class="horizontal-submenu">
<!-- 3x similar div (like above) and then: -->
<div class="submenu-container span3">
<ul>
<li>I want to go here</li>
<li>Links</li>
</ul>
</div>
</div>
</li>
<!-- And then goes another main menu item... -->
</ul>
</div>
</div>
</div>
JS:
jQuery(document).ready(function($) {
'use strict';
$('.navbar .nav > li').hover(function() {
var $el = $(this);
$el.addClass('hover');
var $submenu = $el.find('.horizontal-submenu');
if ($submenu.is(':hidden')) {
$submenu.slideDown(200);
}
}, function() {
var $el = $(this);
$el.removeClass('hover');
var $submenu = $el.find('.horizontal-submenu');
if ($submenu.is(':visible')) {
$submenu.hide();
}
});
});
Problem
I think I need to add a little delay before both - sliding Down submenu on very first hover and - changing submenu content (when switching/hovering to another menu item).
Why?
When you hover on "Dropdown" and want to choose "I want to move here":
You have to go down from "Dropdown" item and then to the right - which is ok (but not very usable).
Problem is, when you go like the image is showing (from the "Dropdown" straight to the "I want to move here" - you catch "Third item" on your way and immidiatelly see the content that belongs to "Third item". And that's not very good.
If you could show me how to delay/ignore hover on my menu items for very short time, I would be grateful. (I found great example behavior of menu on: http://FEI.com)
Ben Kamens from Khan Academy wrote an article regarding this exact problem, outlining how Amazon.com solved it. It is a great read!
http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown
He also put together a jQuery plugin to solve this problem with a working demo. You can find it on GitHub here:
https://github.com/kamens/jQuery-menu-aim
http://htmlpreview.github.io/?https://github.com/kamens/jQuery-menu-aim/blob/master/example/example.html
$(function($) {
var m;
var timer="";
var wait=200;
active=function(){
$('.navbar .nav > li').mouseover(function() {
m = $(this);
if(timer==""){
test();
unb();
timer = setTimeout(reb,wait);
}
});
}
test = function(){
$(".horizontal-submenu").stop().hide(300);
m.find(".horizontal-submenu").stop().show(300);
};
unb = function(){
$('.navbar .nav > li').unbind('mouseover');
};
reb = function(){
timer="";
active();
};
$(".horizontal-submenu").hide(300);
active();
});
Adjust 'wait' for your best timing; You can just copy and try on your script.
This might be what you are looking for:-
http://cherne.net/brian/resources/jquery.hoverIntent.html
From this you need 2 lines on your web page to activate the hover to working properly
1) Loading script hoverIntent
2) Change from hover to hoverIntent in your jQuery
please try setTimeout. It always does the trick.

Categories