Bouncing submenu jquery - javascript

I´m doing a menu that every item has it´s submenu. this is the markup:
<ul id="menu">
<li>
TITLE 1
<ul class="submenu">
<li>
sub1
</li>
<li>
sub2
</li>
</ul>
</li>
<li>
TITLE 2
<ul class="submenu">
<li>
sub1
</li>
<li>
sub2
</li>
</ul>
</li>
<li>
TITLE 3
</li>
<li>
TITLE 4
</li>
</ul>
css
.submenu{display:none}
script
function show_submenu(that) {
$('ul.submenu').slideUp();
$(that).next('ul.submenu:first').slideDown();
}
The problem I have is that if I click over an item, it slides down it´s submenu, BUT if I click over it again, it slidesup and slidesdown again it´s submenu, which is already opened... kind of weird effect for the user... any ideas how to fix it?

You need to check whether the existing submenu is visible already. If it is, you don't want to slide it down again.
var $submenu = $(that).next('ul.submenu:first'),
viz = $submenu.is(":visible");
$('ul.submenu').slideUp();
if (!viz) {
$(that).next('ul.submenu:first').slideDown();
}
http://jsfiddle.net/ExplosionPIlls/zep6H/

use toggle in jquery
$('#foo').toggle(showOrHide);
http://api.jquery.com/toggle/

It's doing exactly what you coded it to do. Instead, use .slideToggle();
function show_submenu(that){
$(that).next('ul.submenu:first').slideToggle();
}
jsFiddle example

this should help
function show_submenu(that){
if(!$(that).next('ul.submenu:first').is(":visible")){
$('ul.submenu').slideUp();
$(that).next('ul.submenu:first').slideDown();
}
}

Related

How do you use JQuery UI menu with ENTER key?

I'm working on an application that needs to be fully keyboard controllable, everything is working great up until now, but i can't make the JQuery UI Menu widget works when using the ENTER key.
From the documentation, there seems to be no specifics method to make this work so i'm using "onclick" on the list elements
<li onclick="alert('Books Action')"><div>Books</div></li>
Here is a jsfiddle (https://jsfiddle.net/djbh6r82/) with the example from JQuery UI documentation and an alert on the first menu item -> It works fine when i click on it but with 'ENTER' it just bring me back to the start (focus on menu is not lost)
$(function() {
$("#menu").menu();
});
.ui-menu {
width: 150px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>
<ul id="menu">
<li class="ui-state-disabled">
<div>Toys (n/a)</div>
</li>
<li onclick="alert('Books Action')">
<div>Books</div>
</li>
<li>
<div>Clothing</div>
</li>
<li>
<div>Electronics</div>
<ul>
<li class="ui-state-disabled">
<div>Home Entertainment</div>
</li>
<li>
<div>Car Hifi</div>
</li>
<li>
<div>Utilities</div>
</li>
</ul>
</li>
<li>
<div>Movies</div>
</li>
<li>
<div>Music</div>
<ul>
<li>
<div>Rock</div>
<ul>
<li>
<div>Alternative</div>
</li>
<li>
<div>Classic</div>
</li>
</ul>
</li>
<li>
<div>Jazz</div>
<ul>
<li>
<div>Freejazz</div>
</li>
<li>
<div>Big Band</div>
</li>
<li>
<div>Modern</div>
</li>
</ul>
</li>
<li>
<div>Pop</div>
</li>
</ul>
</li>
<li class="ui-state-disabled">
<div>Specials (n/a)</div>
</li>
</ul>
Am I doing this wrong ? I tried different thing ( instead of div, onclick on div instead of ul) but nothing seems to work
When you review the API Docs, you will see under https://api.jqueryui.com/menu/ the following details:
Keyboard interaction
ENTER/SPACE: Invoke the focused menu item's action, which may be opening a submenu.
UP: Move focus to the previous menu item.
DOWN: Move focus to the next menu item.
RIGHT: Open the submenu, if available.
LEFT: Close the current submenu and move focus to the parent menu item. If not in a submenu, do nothing.
ESCAPE: Close the current submenu and move focus to the parent menu item. If not in a submenu, do nothing.
Typing a letter moves focus to the first item whose title starts with that character. Repeating the same character cycles through matching items. Typing more characters within the one second timer matches those characters.
Disabled items can receive keyboard focus, but do not allow any other interaction.
So the Enter is already engaged and will trigger the select event for the Menu. You will then want to perform some action in the select callback.
$(function() {
$("#menu").menu({
select: function(e, ui) {
console.log(ui.item.text().trim(), "Selected");
}
}).focus();
});
.ui-menu {
width: 150px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>
<ul id="menu">
<li class="ui-state-disabled">
<div>Toys (n/a)</div>
</li>
<li>
<div>Books</div>
</li>
<li>
<div>Clothing</div>
</li>
<li>
<div>Electronics</div>
<ul>
<li class="ui-state-disabled">
<div>Home Entertainment</div>
</li>
<li>
<div>Car Hifi</div>
</li>
<li>
<div>Utilities</div>
</li>
</ul>
</li>
<li>
<div>Movies</div>
</li>
<li>
<div>Music</div>
<ul>
<li>
<div>Rock</div>
<ul>
<li>
<div>Alternative</div>
</li>
<li>
<div>Classic</div>
</li>
</ul>
</li>
<li>
<div>Jazz</div>
<ul>
<li>
<div>Freejazz</div>
</li>
<li>
<div>Big Band</div>
</li>
<li>
<div>Modern</div>
</li>
</ul>
</li>
<li>
<div>Pop</div>
</li>
</ul>
</li>
<li class="ui-state-disabled">
<div>Specials (n/a)</div>
</li>
</ul>
Giving it focus up front allows it to already be invoked.

How to toggle <li> in a nested list?

I'm trying to be able to toggle these sub menus one at a time, I'm getting lost in nests and cant quite figure out how to target the correct list item,
I found that I should be using find() instead of children() as it can go deeper in the nest but still no luck in getting it working.
<ul>
<li>Profile</li>
<li>Edit</li>
<li class="drop-nav"> See your products
<ul>
<li class="drop-nav"> Mens
<ul>
<li> jumpers </li>
<li> t shirts </li>
</ul>
</li>
<li class="drop-nav"> Womens
<ul>
<li> hoodies </li>
<li> leggings </li>
</ul>
</li>
</ul>
</li>
</ul>
$(".drop-nav").on("click", function(e){
e.preventDefault();
});
li ul{
display: none;
}
You could use $(this).find('ul').eq(0) to get the ul, but I would delegate the changing of the display to the stylesheet, but use javascript to add a class where applicable. This will give you many more options for the design of your dropdown later.
$(".drop-nav").on("click", function(e) {
e.preventDefault()
// don't allow the event to fire horizontally or vertically up the tree
e.stopImmediatePropagation()
// switch the active class that you can use to display the child
$(this).toggleClass('active')
})
/* don't target ll list items in you page, be more specific */
.drop-nav > ul {
display: none;
}
.drop-nav.active > ul {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Profile</li>
<li>Edit</li>
<li class="drop-nav"> See your products
<ul>
<li class="drop-nav"> Mens
<ul>
<li> jumpers </li>
<li> t shirts </li>
</ul>
</li>
<li class="drop-nav"> Womens
<ul>
<li> hoodies </li>
<li> leggings </li>
</ul>
</li>
</ul>
</li>
</ul>
I would add more descriptive class names in your markup, and make them easier to target with CSS and jQuery.
To toggle the menus you could do something like the following:
$(".dropdown-trigger1").on("click", function() {
// Toggle the first menu
$(".dropdown-one").toggleClass("open");
// Close the submenus
$(".dropdown-two").removeClass("open");
});
$(".dropdown-trigger2").on("click", function(e) {
// Prevent a click on a submenu from closing the menu
e.stopPropagation();
// Close any open submenu
$(".dropdown-two").removeClass("open");
// Open the submenu that has been clicked
$(this).find(".dropdown-two").toggleClass("open");
});
li ul {
display: none;
}
.dropdown-one.open {
display: block;
}
.dropdown-two.open {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Profile</li>
<li>Edit</li>
<li class="dropdown-trigger1"> See your products
<ul class="dropdown-one">
<li class="dropdown-trigger2"> Mens
<ul class="dropdown-two">
<li> jumpers </li>
<li> t shirts </li>
</ul>
</li>
<li class="dropdown-trigger2"> Womens
<ul class="dropdown-two">
<li> hoodies </li>
<li> leggings </li>
</ul>
</li>
</ul>
</li>
</ul>
You haven't described about how you activate each sub-menu, so I will describe solution little bit abstractly. Solution is based on your HTML structure an will work if you wouldn't change it.
$('.drop-nav a').on('click', function() {
// This next method returns next element in DOM that is after clicked a link.
// Based on your HTML it would be ul that holds your sub-menu.
var subMenu = $(this).next();
// Here using subMenu selector to make something with sub-menu...
// Example: adding CSS inline to sub. In your situation it may be something else...
$(subMenu).css({ 'display' : 'block' });
});

.click() functionality when clicking elements

Basically i want to click on a tab and a drop down menu appears then when you re-click the same tab or any of the others I want it to hide that tab/show the other tab if clicked on the same/other tab.
I tried
$('.click').click(function() {
$(this).find('.sub-nav-list').toggleClass('active');
});
and tried
$('.click').click(function() {
$('.sub-nav-list').removeClass('active');
$(this).find('.sub-nav-list').toggleClass('active');
});
but cant work it out! any insight? Thanks
html:
<nav class="secondary-nav">
<ul class="list clearfix">
<li class="leaders click">Leadership <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Management</li>
<li>Board of Directors</li>
</ul>
</li>
<li class="contact click">Contact Info <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Email Notification</li>
<li>Information Request</li>
</ul>
</li>
<li class="docs click">Documents <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Governance Documents</li>
<li>Press Release</li>
<li>Reports & Presentations</li>
<li>Sec Filings</li>
<li>Frenquently Asked Questions</li>
<li>Tax Information</li>
</ul>
</li>
<li class="research click">Research <span class="arrow">></span>
<ul class="sub-nav-list">
<li>Dividends and Distributions</li>
<li>Stock Information</li>
<li>Analyst Coverage</li>
<li>Market Makers</li>
</ul>
</li>
</ul>
</nav>
I can see at least two possible issues there.
1) sub-nav-list is not a children of click element. If they are on the same level something like that might work:
$('.click').click(function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});
2) You have these elements generated dynamically - so you need use on with selector of any parent element that exists before you dynamically generate your sub-menus (let say nav-list):
$(".click").on("click", ".nav-list", function() {
$(this).parent().find('.sub-nav-list').toggleClass('active');
});

Vertical CSS slide menu pushing the site up on click

The submenu on each menu item slides underneath the main menu item instead of sliding out whenever I click on a menu item, which is what it's supposed to do. Problem is the site itself automatically scrolls up. Its as if the main menu items have a link to them that is anchored to the top of the site. I click on them, the submenu slide out, but the site itself scrolls up everytime.
How to make the code cross-browser compatible?
The javascript code:
<script type="text/javascript">
<!--//--><![CDATA[//><!--
startList = function() {
if (document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
node = navRoot.childNodes[i];
if (node.nodeName=="LI") {
node.onclick=function() {
this.className = (this.className == "on") ? "off" : "on";
}
}
}
}
}
window.onload=startList;
//--><!]]>
</script>
The html code:
<ul id="nav">
<li>Home </li>
<li>About >
<ul>
<li>History </li>
<li>Team </li>
<li>Offices </li>
</ul>
</li>
<li>Services >
<ul>
<li>Web Design </li>
<li>Internet Marketing </li>
<li>Hosting </li>
<li>Domain Names </li>
<li>Broadband </li>
</ul>
</li>
<li>Contact Us >
<ul>
<li>United Kingdom</li>
<li>France</li>
<li>USA</li>
<li>Australia</li>
</ul>
</li>
</ul>
Based off of this menu: http://www.pmob.co.uk/temp/drop-down-expand.htm#
The reason is because you have "#" in your hrefs...this is telling the browser to return to the top. You need to return false on your onclick so that the default behavior (navigating to the href) doesn't happen on the items that are not truly "links".
You can always add e.preventDefault() to the event listener to remove all hyperlink-effects after clicked.
Using preventDefault is usually more recommended.
http://jsfiddle.net/Z8Uvj/
$("a").click(function(e){
//your stuff
e.preventDefault();
});

Show/hide content for menu sublink and close the content when click next new link

I'm looking for a solution, it must work in IE also, that I can have the content hidden and then when you click one of the menu items it shows the content. However, the content doesn't hide until a user clicks on the next link...
Please check this link
http://jsfiddle.net/varada/YLX9x/
you can use jquery hide() and show() functions for that.
Let the id of div that is to be hidden be hidden_div, let menu item be menu_item, next button be next,
Import the jquery.js
and write the ready function as below..
$(document).ready(function() {
$('#menu_item').click(function() {
$('#hidden_div').show();
});
$('#next').click(function() {
$('#hidden_div').hide();
});
});
or if you mean the content be visible till he click the next link on the menu item, add a class name say, menu_class to the menu items and write the code
$('.menu_class').click(function() {
$('#hidden_div').hide();
});
instead of $('#next').click(function()
if you have a menu like
<ul>
<li class='menu_class'>item 1</li>
<li id='menu_item' >item 2</li>
<li class='menu_class'>item 3</li>
</ul>
and the div
<div id='hidde_div' style='display:none'>
content
</div>
then if you click item 2 the div will get displayed. and if you click item 1 or item 3 it will get hidden. make sure you are using the code $('.menu_class').click(function() {
html:
<li class="main">Web
<ul>
<li>Designing</li>
<li>Development</li>
</ul>
</li>
<li class="main">IT
<ul>
<li>Sales & Service</li>
<li>CCTV</li>
<li>DVR</li>
</ul>
</li>
<li class="main">ITES
<ul>
<li>BPO</li>
<li>Online Portal</li>
<li>Online Marketing</li>
</ul>
</li>​
js:
$(document).ready(function(){
$('li ul:not(:first)').hide();
$('ul li').click(function(){
$(this).closest('.main').next().find('ul').show();
$(this).closest('ul').hide();
});
});​
http://jsfiddle.net/7QheB/

Categories