I have a problem with menu delay. I can't add delay when I not hover on submenu. What can I change to delay the submenu for 1 second when I not hover on it. I have to delete this delay when I hover on main menu.
better explenation:
When you hover the main menu items, the delay of the first item keeps the menu item open, while the mouse is already on the second menu item. See gif below.
How will I be able to fix this? Keeping the delay, but when another menu is open, hiding the menu item instantly.
problem
structure of html (compressed for better view):
<div>
<ul class="menu_type_top">
<li>Hello<li/>
<li>hi
<ul>
<li>Hello</li>
<li>hi</li>
</ul>
<li/>
<li>ok<li/>
</ul>
</div>
Code in javascirpt to correct:
$('ul.menu_type_top > li').on('mouseover', function(e){
var ulObj = $(this).find("ul:first");
console.log(ulObj);
ulObj.show();
var menu_height = ulObj[0].clientHeight + 300;
$('ul.menu_type_top').css({ height: menu_height });//pokazanie podmenu bo warstwa jest w divie gdzie overflow: hidden
}).on('mouseout', function(e){
$(this).find("ul:first").hide();
$('ul.menu_type_top').css({ height: 40 });//powrót do normalnej wysokości menu
});
$('ul.menu_type_top li li').on('mouseover',function(e){
if($(this).has('ul').length) {
}
$('ul:first',this).show();
}).on('mouseout',function(e){
$('ul:first', this).hide();
});
Related
This Meteor code is expected to show and hide a <ul id="Bulb"> element. An event fires the first time shows the element but when clicked again it failed to hid it.
Please note the browser console.log($('#' + category)) image showing both events. Any idea why the second click not hiding the element and how to make it hide on the second event so that the toggle works?
Thank you.
'click .category': function(e){
let category = e.target.innerText
$('#' + category).toggle()
console.log($('#' + category))
}
.horizontal {
display: inline;
}
.group, .subGroup {
display: none;
}
<li class="category" data-category={{category}}> <img src="/{{category}}.svg"/>{{category}}
<ul id={{category}} class="no-bullets group">
<!-- the last word is the argument passed to the helper function -->
{{#each categories category}}
<li class="horizontal" data-category={{category}}>{{this}}</li>
{{/each}}
</ul>
Fix but with unwanted side effect
The reason is that the first click gives a value to e.target.innerText which is different than the value it gets in the second click.
The second value includes all the "innerText" of all the li items which are now visible in the child ul.
So instead of using let category = e.target.innerText I used:
let category = e.target.getAttribute('data-category')
and this value does not change between click as did the innerText.
The problem side effect of this is that clicking the li elements inside the child ul triggers the toggle which is not what I want.
First things first, a fiddle: http://jsfiddle.net/d7wfv8w8/
I have a navbar with a logo, search form and a Categories link. When somebody moves over it with the mouse, it should open the wrapper-categories div, which is display: none; by default.
I got it working, except the div is closing when you then move the mouse over the div that opened. I thought I could get it to stay open if I used .navbar .toggle to tell it that the parent is .navbar and it should stay open as long as the mouse is anywhere over that parent div.
How can I achieve this?
Here is my HTML:
<div class="navbar">
<div class="wrapper-header">
<ul>
<li class="">Logo Here</li>
<li class="">Search Here</li>
<li class="">Categories</li>
</ul>
</div>
<div class="wrapper-categories">
Categories Here
</div>
</div>
And the jQuery:
$(".navbar .toggle").hover(function (event){
event.preventDefault();
$(".wrapper-categories").slideToggle("fast");
});
You can achieve this by binding the hover function to the element wrapping both wrapper-header and wrapper-catagories. This will cause the hoverOut to only be called when it leaves the wrapper for both elements. Keeping both of your required divs open.
Fiddle: http://jsfiddle.net/d7wfv8w8/5/
Late to the party but change your class' to ID's and give this a go. Works for me.
$(document).ready(function(){
$( "#toggle" ).hover(
function() {
$( "#wrapper-categories" ).slideDown({
left: "+=50",
height: "toggle"
}, 500, function() {
// Animation complete.
});
}
);
var inArr = {toggle:false, wrapper-categories:false};
$('#toggle, #wrapper-categories').mouseover(function(){
inArr [$(this).attr('id')] = true;
});
$('#toggle, #wrapper-categories').mouseout(function(){
inArr [$(this).attr('id')] = false;
setTimeout(function(){
if(!inArr.toggle && !inArr.wrapper-categories) {
$('#navArea').slideUp(500);
}
},100);
});
});
I've written a simple accordion-style navigation sidebar (several lists of nav options):
<nav>
<ul>
<li class="section">
<h2>Section 1 Header</h2>
<ul>
<li>First Option</li>
<li>Second Option</li>
<li>Third Option</li>
</ul>
</li>
<li class="section">
<h2>Section 2 Header</h2>
<ul>
<li>First Option</li>
<li>Second Option</li>
<li>Third Option</li>
</ul>
</li>
</ul>
...
</nav>
jQuery script that hides/reveals lists of nav options when a given section's h2 is clicked:
$(document).ready(function() {
$('li.section ul').hide();
$('li.section h2').click(function() {
$(this).toggleClass('active');
$(this).parent().children('ul').toggle('blind', { direction: 'vertical' });
});
});
The whole effect works fine, but I'm running into trouble with double-clicks.
The animation of the accordion effect is handled by the script above--but the "highlight" color of the activated header area is handled with a simple CSS3 transition, which takes effect when the class is toggled by the script.
When I double-click the h2, my toggle blind animation fires only once (which I like), but the toggleClass happens twice (so I'm switched quickly into and out of the 'active' state--leaving it out of sync with the state of the blind animation).
Is there a way to ignore the second click of a double-click so this toggle only happens once per toggle animation?
Or maybe it's better to think of it as ignoring a given section's h2 click events while the toggle blind animation is happening on that section...?
Try making the header area "active" after toggle completion. I have not tested, just make a try.
$(document).ready(function() {
$('li.section ul').hide();
$('li.section h2').click(function() {
var thiz = $(this);
thiz.parent().children('ul').toggle('blind', { direction: 'vertical' }, function() {
// make it active after toggle
thiz.toggleClass('active');
});
});
});
Maybe..
....
$('li.section h2').bind('click dblclick',function() {
....
or
$(document).ready(function() {
$('li.section ul').hide();
$('li.section h2').click(function() {
$t = $(this); /* Aliased for ease of use */
if( !$t.hasClass('active') ){
/* Not marked as Active yet */
$('li.section h2.active')
.not($t)
.removeClass('active')
.parent().children('ul')
.toggle('blind', { direction: 'vertical' });;
/* Above assumes you want only one h2 to be active at a time.
If not, remove the above two lines... */
$t
.toggleClass('active')
.parent().children('ul')
.toggle('blind', { direction: 'vertical' });
}else{
/* Already Active! Do Nothing!! */
}
});
});
I'm making a menu in jquery. You can see it at http://mywash.dk/testtest/index.html
The submenu that is shown from the start (below 'Hvordan') is the active menu so it should always be shown (unless you hover on another menu-item in which case another submenu should show.
It's working okay but has 1 annoying bug. When you hover from 'Hvad' to 'Hvem' it quickly display and hides the active menu before showing the menu it is supposed to.
Any idea why this is the case?
Thanks so much for your help!
Jquery:
$(document).ready(function() {
$('#menu > ul > li:not(.inpath) ul').hide();
$('#menu .inpath ul').show();
$('#menu > ul > li:not(.inpath)').hover(
function() {
$('ul', this).show("slide", { direction: "left" }, 400);
if($('#menu li.inpath ul').is(':visible') && $(this).not('#menu ul li')){
$('#menu li.inpath ul').hide("slide", { direction: "left" }, 400);
}
}, function() {
$('ul', this).hide("slide", { direction: "left" }, 400);
if($('#menu li.inpath ul').is(':hidden') && $(this).not('#menu ul li')){
$('#menu li.inpath ul').show("slide", { direction: "left" }, 400);
}
});
});
Html:
<div id="menu">
<ul>
<li class="test">Hvem
<ul>
<li class="first-item">Submenu</li>
</ul>
</li>
<li class="test">Hvad
<ul>
<li class="first-item">Produkter</li>
<li class="activeitem"><a href="cases.html" >Leveringer</a></li>
</ul>
</li>
<li class="inpath test">Hvordan
<ul>
<li class="first-item">Reklame</li>
<li>PR</li>
<li>Websites</li>
<li>Illustrationer</li>
</ul>
</li>
<li class="last-item test">Sådan!</li>
</ul>
<div class="clear"><!--clearfix--></div>
</div>
Well, it does, what you tell it. Break it down:
The main nav is visible, child navs are hidden
Mouse enters a child: Scroll away main, scroll in child
Mouse leaves child again: Scroll away child, scroll in main
Mouse enters another child: Scroll in child, scroll away main. But at the time of this event, the animation of 3. hasn't finished yet. So, the new animations just stack on top of the currently queued.
How to fix?
You need to cancel the current animations on the main nav. Let your hover-in function look like this:
function() {
$('ul', this).show("slide", { direction: "left" }, 400);
if($('#menu li.inpath ul').is(':visible') && $(this).not('#menu ul li')){
$('#menu li.inpath ul').stop(true, true).hide("slide", { direction: "left" }, 400);
// ----------------------------^ stop all current animations and clear the queue
}
}
or you query the length of the main queue on entering:
$('#menu li.inpath ul').queue().length > 0
// -> then stop
The basic idea is laid out in the jQuery docs and explained in this SO answer, too. Basically, every time you put an animation on a jQuery object, the animation is queued and executed after all currently running animations.
So if the mouse enters a navigation point, you have to check, if the main navigation is in motion right now by looking at its queue length. If there are animations piled up, you can call .stop(true, true) to empty the queue and set the element in a state as if all the animations would have finished (the double-true). Then you can hide it, and no animation will come in your way.
If it is not in motion, i.e., if it has an empty queue, and if it is visible, (and only in this case,) you have to slide it out of view.
I have a project that uses drop-down menus that are nested ul's, like so:
<ul id="nav">
<li id="thome" class="navtab">
HOME
<ul id="subnav_home" class="submenu">
<li>Dashboard</li>
<li>SMS</li>
<li>Email</li>
<li>Twitter</li>
</ul>
</li>
</ul>
Using jQuery, I've added a .hover() to the .navtab li that .show()s the .submenu ul. The problem is that when the cursor moves into the new ul, the .hover()-out for the .navtab fires, .hide()ing the sub-menu, despite the fact that I have the height of the li so that it entirely wraps the .submenu ul.
I've tried adding a delay to the .hide(), but if you pass your cursor over the navtab bar quickly, you get all of the sub-menus at once.
Any solutions for me? Here's the relevant JavaScript. The hide() function is identical to .show() except that it shrinks the height and hides the ul (obviously).
$('.navtab').hover(
function(){
tabShowSubnav($(this).attr('id'));
},
function(){
tabHideSubnav($(this).attr('id'));
});
function tabShowSubnav(menu){
var sb = '#' + menu + ' > .submenu';
var tb = '#' + menu;
$('.navtab').each(function(){
if (!$(this).hasClass('current_page')){
$(tb).addClass('nav_hover');
}
});
$(tb).css('height','239px');
$(sb).show();
}
$('.navtab').hover(
function() {
$(this).children(".submenu").show().children('current_page').addClass("nav_hover");
},
function() {
});
$(".submenu").mouseout(function(){
$(this).hide();
});
$('.navtab').hover(
function() {
$(this).children(".submenu").show().children('.current_page').addClass("nav_hover");
},
function() {
$(this).children(".submenu").hide();
});
This worked for me.
I finally had to go with the jQuery plugin hoverIntent, that ignores children for the purpose of mouseout.