I am trying to achieve a simple drop-down menu with the following HTML structure. This structure is mandatory (I think) as explained in the illustrations below.
<nav role="navigation">
<ul id="main-menu" class="nav top-nav clearfix">
<li id="menu-item-1" class="menu-item">Menu 1</li>
<li id="menu-item-2" class="menu-item">Menu 2</li>
<li id="menu-item-3" class="menu-item">Menu 3</li>
</ul>
<ul id="sub-menu-1" class="sub-menu nav clearfix">
<li class="menu-item">Sub Menu 1.1</li>
<li class="menu-item">Sub Menu 1.2</li>
<li class="menu-item"><a href="#">Sub Menu 1.3/a></li>
</ul>
<ul id="sub-menu-2" class="sub-menu nav clearfix">
<li class="menu-item">Sub Menu 2.1</li>
<li class="menu-item">Sub Menu 2.2</li>
<li class="menu-item"><a href="#">Sub Menu 2.3/a></li>
</ul>
</nav>
To get a better idea of what I am trying to achieve I've made the following illustrations:
Simple menu with items arranged with inline blocks. As you can see, the menu scales to 100% of the container and has all the items arranged in center.
When hovering over a menu item which has a submenu. In the illustration that's Menu 1 which has Sub Menu 1 and it needs to display it on mouse hover, like a simple <ul><li><ul></ul></li></ul> would do. As you can see the submenu has to scale to 100% of the container and has all the items arranged in center.
I think the best approach is with javascript (not sure you can do this with only CSS), but I am kind off stuck. The sub menu appears on main menu item hover, but as soon as I hover out into the sub menu in order to navigate, the sub menu disappears. Anyway, this is the javascript:
$('nav #main-menu .menu-item a').hover(
function() {
var id = $(this).parent().attr('id');
id = id.substr(id.length - 1);
submenu = $('#sub-menu-' + id);
submenu.show();
},
function() {
var id = $(this).parent().attr('id');
id = id.substr(id.length - 1);
submenu = $('#sub-menu-' + id);
submenu.hide();
}
);
I am pretty sure that there is a better way to do this.
I've also set up a FIDDLE for better understanding.
//show sub menu when we hover over an item
$('nav #main-menu > .menu-item')
.on('mouseenter', function() {
$('.sub-menu').hide();
var id = $(this).attr('id');
id = id.substr(id.length - 1);
$('#sub-menu-' + id).show();
});
//hide submenu when the mouse goes away
$('nav').on('mouseleave', function() { $('.sub-menu').hide(); });
Modified your fiddle here: http://jsfiddle.net/3z8MR/10/
Edit
Add this line to conform to your specs in the comments
$('.sub-menu').on('mouseleave', function() { $(this).hide(); });
Related
I need to open a submenu, clicking on the parent element. I could do it this way
$(function(){
$('li.dropdown > a').on('click',function(event){
event.preventDefault();
$(this).toggleClass('selected');
$(this).parent().find('ul').first().toggle(300);
$(this).parent().siblings().find('ul').hide(200);
//Hide menu when clicked outside
$(this).parent().find('ul').parent().mouseleave(function(){
var thisUI = $(this);
$('html').click(function(){
thisUI.children(".dropdown-menu").hide();
thisUI.children("a").removeClass('selected');
$('html').unbind('click');
});
});
});
});
But, sometimes I have an actual link as a parent element. And I'd want to go to that link on click. And open the dropdown otherwise. Tried with a click on dropdown:before/ dropdown:after pseudoelements with no luck. And I can't manage to do it adding a span inside dropdown div.
Thank you for any help.
LE: My HTML structure looks like this
<nav id="main-nav">
<ul>
<li>Home</li>
<li class="dropdown">Main Cat
<ul class="dropdown-menu">
<li>Sub Cat1</li>
<li>Sub Cat2</li>
<li>Sub Cat3</li>
</ul>
</li>
<li>Second Cat</li>
</ul>
</nav>
In short, I have a 2 main links (Private Car and Commercial Vehicle) each with a specific class attached to their anchor tags. The same class names are used on the li tags of a second sublink ul to match them with to two top links. The idea is that each time a main link is clicked, the following happens:
The sublink ul slides up
All the li's inside are hidden
The li's with the corresponding main link class are shown
The sublink ul slides down showing only the correct li's
Unfortunately that is not the order that the functions fire in. What happens is this:
The sublink ul slides up
The sublink ul slides down
All list elements inside are hidden
The relevant list elements slide down
Any idea on how I can get the order to fire as I want it?
Here is the code
$('.insurer ul.toplinks a').click(function(e) {
e.preventDefault();
var sublinkCategory = $(this).attr('class'),
subLinksToShow = $(this).parent().parent().parent().find('li.' + sublinkCategory),
subLinksList = $(this).parent().parent().parent().find('ul.sublinks'),
allLinks = $(subLinksList).find('li');
// First time
if ($(subLinksList).is(":hidden")) {
$(subLinksToShow).slideDown();
$(subLinksList).slideDown();
// List visible but new links invisible
} else if ($(subLinksList).is(":visible") && $(subLinksToShow).is(":hidden")) {
$(subLinksList).slideUp(function() {
$(allLinks).hide(function() {
$(subLinksList).slideDown(function() {
$(subLinksToShow).slideDown();
});
});
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="toplinks">
<li>Private Car</li>
<li>Commercial Vehicle</li>
</ul>
<ul class="sublinks">
<li class="privatecar">Key Facts</li>
<li class="privatecar">Policy Wording</li>
<li class="commercialvehicle">Key Facts</li>
<li class="commercialvehicle">Policy Wording</li>
</ul>
Your code isn't working while we don't have the fully code.
This works, note the comments in the code to see what happens on the line under the comment.
$(function() {
// hide by default
$('.sublinks').hide();
$('.toplinks a').on('click', function(e) {
e.preventDefault();
// get the classname
var cl = $(this).attr('class');
// slide up
$('.sublinks').slideUp("slow", function() {
//on callback (= after slide up is done)
// show all links
$('.sublinks li').show();
// hide the ones not having the right class
$('.sublinks li:not(.'+cl+')').hide();
// slide down again
$('.sublinks').slideDown("slow");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="toplinks">
<li>Private Car</li>
<li>Commercial Vehicle</li>
</ul>
<ul class="sublinks">
<li class="privatecar">private Key Facts</li>
<li class="privatecar">private Policy Wording</li>
<li class="commercialvehicle">commercial Key Facts</li>
<li class="commercialvehicle">commercial Policy Wording</li>
</ul>
So I have this vertical menu that slides down when you click on the parent item to display the children elements and when you click on a child element it takes you to the link.
My problem is that when you click on the link the whole submenu slides up because of the slideToggle function on it - how can I stop the slide up from happening only if a link is clicked?
My Menu:
<ul id="menu-top" class="menu">
<li class="has-submenu">
Portfolio
<ul class="sub-menu" style="display: none;">
<li class="menu-item">
Book I
</li>
</ul>
</li>
<li class="has-submenu">
Headshots
<ul class="sub-menu" style="display: none;">
<li class="menu-item">
Men
</li>
</ul>
</li>
<li class="regular-link">
Personal Work
</li>
</ul>
JS:
jQuery('#menu-top').children().click(function(e){
var $next = jQuery(this).find('.sub-menu');
var $child =('.active-menu');
$next.stop().slideToggle('slow').toggleClass('active-menu');
jQuery(".sub-menu").not($next, $child).slideUp('slow').removeClass('active-menu');
});
jQuery('.has-submenu > a').click(function(e){
e.preventDefault();
});
Use stopPropagation to prevent the event from bubbling.
jQuery('.submenu a').click(function(e){
e.stopPropagation();
});
To stop the slideToggle menu from sliding up when clicking the ul's children links, you can use the jquery function stopPropogation() on the click event of the link itself.
$(".shop-by-dept ul li a").click(function(e){
e.stopPropagation();
});
This will prevent the slideToggle() action from sliding the menu up, while the browser loads the next page.
I have the following simple 3 level menu structure:
<nav class="main-nav" class="list">
<ul>
<li class="first lev1">Home</li>
<li class="lev1">Lev 1 1</li>
<li class="lev1 hasc active">
Lev 1 2
<ul>
<li class="first lev2 hasc">
Lev 2 1
<ul>
<li class="first lev3">Lev 3 1 </li>
<li class="lev3">Lev 3 2</li>
</ul>
</li>
</ul>
</li>
<li class="lev1 hasc active">Lev 1 3</li>
</ul>
</nav>
I'm trying to make the menu work so that the second level menu slides open when it has children but is an active link when it does not and then all 3rd level links are always active links.
The following jquery code works for all the required functionality for the 2nd level menu (prevents default and opens the 3rd level if there are children, but if not makes the link active) the problem is that i'm not sure how to over ride the prevent default for the third level?
$(".lev2").click(function (event) {
event.preventDefault();
if ($(this).hasClass('on')) {
$(this).children('ul').slideUp();
$(this).removeClass('on');
} else {
$(this).children('ul').slideDown();
$(this).addClass('on');
}
});
I've looked into starting at the root of the menu class 'main-nav' and then try to branch the code but as it is nested I'm not finding any logic that will work? any ideas most welcome.
The problem seems to be that you´re binding the click event to the entire li element and not just the link.
Try this instead:
$(".lev2 > a").click(function (event) {
event.preventDefault();
$(this).parent().toggleClass('on').children('ul').slideToggle();
});
It binds the event to the link and toggles your actions on the parent li and ul for the next level.
Live example at jsFiddle
This works. Just checks for a level 3 click first to tell the level 2 function whether level 3 has been clicked or not.
$(document).ready(function(){
var level2 = true;
$("li.lev3").click(function(){
level2 = false;
});
$("li.lev2").click( function(event){
if (level2){
alert ("lvl2");
event.preventDefault();
if($(this).hasClass('on')) {
$(this).children('ul').slideUp();
$(this).removeClass('on');
}else{
$(this).children('ul').slideDown();
$(this).addClass('on');
}
}
});
});
I'm using the following script to generate a horizontal drop down menu on a site. It works wonderfully in Firefox and Safari, but fails in IE8 (surprise surprise). The intended behavior is that when a main menu item with a submenu is hovered over in the navigation list, the corresponding submenu will appear and any existing submenus in the .submenu div will disappear. In IE8, though, only one of the menu items will display its corresponding submenu (and then only after the link to the left of it, a link without a submenu, has been hovered), and its doing so disables the CSS hover effect on the links. Here's a live example.
I'm not experienced enough in jQuery to know why I might be running into issues, so I'm asking the good folks at StackOverflow for help. Thanks!
(Edit: I'm also running ie7.js on this particular page-- I don't know if that will effect anything or not, but I thought it would be worth mentioning)
$(document).ready(function() {
$('.submenu ul').hide(); //hide all submenus
var msec = document.location.href; //get current url
var mshref = msec.split("/"); //trim URL to include only current section
$('.submenu ul[class~='+mshref[3]+']').show(); //show submenu belonginging to current section
$('.topmenu a').hover(function(){
var msection = $(this).attr("href");
var msechref = msection.split("/");
if($('.submenu ul[class~='+msechref[3]+']').length){ //if there's a submenu belonging to this section
$('.submenu ul').hide();//hide all submenus
$('.submenu ul[class~='+msechref[3]+']').show(); //show the submenu for the section being hovered over
}
else
{
$('.submenu ul').hide();//hide all submenus
$('.submenu ul[class~='+mshref[3]+']').show();//show submenu for current section
}
});
});
And here's the HTML.
<nav><!-- top nav -->
<div class="topmenu">
<ul class="section_list">
<li><a class="active" href="http://test/">Home</a></li>
<li>About</li>
<li>ministries</li>
<li>news</li>
<li>sermons</li>
<li>contact</li>
</ul>
</div>
<div class="submenu">
<ul class="category_list about">
<li>join us</li>
<li>our beliefs</li>
<li>our staff</li>
<li>services</li>
</ul>
<ul class="category_list ministries">
<li>adults</li>
<li>children</li>
<li>preschool</li>
<li>youth</li>
</ul>
</div>
</nav><!-- end of top nav -->
EDIT - Can you try this instead of yours:
$(document).ready(function() {
var root = 'http://www.qualprnt.com/clients/fbcw/', $submenu = $('.submenu ul');
$submenu.hide();
var current = location.href.replace(root, '').split('/')[0];
if(current != '') {
$submenu.filter('.' + current).show();
}
$('.topmenu a').mouseenter(function(){
var section = this.href.replace(root, '').split('/')[0];
$submenu.hide();
if(section != '') {
$submenu.filter('.' + section).show();
}
else {
if(current != '') {
$submenu.filter('.' + current).show();
}
}
return false;
});
});
With this solution, you have to change root variable after you move the site to it's original domain. Please let me know if it works.
I will not delete my old answer, maybe it'll be useful for someone else.
OLD ANSWER:
If you're willing to change your CSS and HTML a little then this solution might be better for you.
HTML:
<nav><!-- top nav -->
<div class="topmenu">
<ul class="section_list">
<li><a class="active" href="http://test/">Home</a></li>
<li>About
<ul class="category_list">
<li>join us</li>
<li>our beliefs</li>
<li>our staff</li>
<li>services</li>
</ul>
</li>
<li>ministries
<ul class="category_list">
<li>adults</li>
<li>children</li>
<li>preschool</li>
<li>youth</li>
</ul>
</li>
<li>news</li>
<li>sermons</li>
<li>contact</li>
</ul>
</div>
</nav><!-- end of top nav -->
Javascript:
$(document).ready(function() {
$('.section_list > li').hover(
function() {
var $this = $(this);
if($this.has('ul')) {
$this.find('ul').show();
}
},
function() {
var $this = $(this);
if($this.has('ul')) {
$this.find('ul').hide();
}
}
);
});
change your script tags:
<script>
to
<script type="text/javascript">