Gerald Torres
Gerald Torres

Reputation: 403

JQuery selector not working properly on my multilevel navigation bar

I'm trying to make a simple horizontal navigation bar with multiple levels (but for now, I've only made a navigation bar with one sublevel). I'm following this tutorial here with some modifications:

<ul id = "sample2">
    <li>
        <a href="#">About Us</a>
        <ul>
            <li><a href="#">Website</a></li>
            <li><a href="#">Creator</a></li>
        </ul>
    </li>
    <li>
        <a href="#">Our Products</a>
        <ul>
            <li><a href="#">Product 1</a></li>
            <li><a href="#">Product 2</a></li>
            <li><a href="#">Just give us money</a></li>
        </ul>
    </li>
    <li>
        <a href="#">FAQs</a>
        <ul>
            <li><a href="#">What is this?</a></li>
            <li><a href="#">Why should I care???</a></li>
        </ul>
    </li>
    <li>
        <a href="#">Contact</a>
        <ul>
            <li><a href="#">Telephone</a></li>
            <li><a href="#">Mobile Phone</a></li>
            <li><a href="#">E-mail</a></li>
        </ul>
    </li>
    <li><a href="#">Login</a></li>
</ul>

I used only one id on the main <ul> and I'm accessing the sublevels using #sample2 ul instead of using classes on those.

However, it simply doesn't work when I use the JQuery codes:

$(function () {
    $('#sample2 ul').each(function () {
        $(this).parent().eq(0).hover(function () {
            $('#sample2 ul:eq(0)', this).show(100);
            }, function () {
            $('#sample2 ul:eq(0)', this).hide(100);
        });
    });
});

Again, I only changed the tutorial's .dropdown class to #sample2 ul.

But it does work if I do the same way as the tutorial (i.e. assign either an id or a class on the sublevels), although I think it's unnecessary since those sub-<ul>-s can be selected using css selectors.

What am I doing wrong? Are those sublevels really can only be selected using assigned classes/id on them?

Upvotes: 4

Views: 695

Answers (5)

devstruck
devstruck

Reputation: 1507

This should do the trick. jsFiddle

$(function () {
    $('#sample2').on('hover', 'li', showSubMenu);
    $('#sample2').on('mouseleave', hideSubMenus);
});

function showSubMenu(){
    $(this).siblings().children('ul').hide(100);
    $(this).children('ul').show(100);
}
function hideSubMenus(){
    $(this).find('ul').hide(100);
}

EDIT: It seems like you have some confusion about jQuery and how to use selectors (particularly selectors with context e.g. $(selector, context)).

In your example, $('#sample2 ul') will select every ul that is a descendant of #sample 2. If you wanted to add the same hover effect to each ul, $('#sample2 ul').hover(handler) or $('#sample2 ul').on('hover', handler) will do that for you. The problem is, you can't hover over hidden items. So what you really want is to select the li under #sample2 and attach your handler to their hover event.

Within your hover event handler, you use the selector $('#sample2 ul:eq(0)', this). The 'this' in that selector provides the context within which the #sample2 ul:eq(0) will be looked for. In an event handler, this refers to the element tied to that event. In this case, the hovered-over li. Eq(0) has no place inside the quotes of the selector, and as a general rule, should be avoided as part of any jQuery selector. Because there is no #sample2 element within the context of this and because the :eq(0) malforms the selector, $('#sample2 ul:eq(0)', this) will return an empty jQuery object (nothing selected). What you wanted in your handler was $(this).children('ul'). Which will get the ul that is a direct child of the li currently hovered over.

Upvotes: 1

CKKiller
CKKiller

Reputation: 1422

EDIT: got it this time, and I've tested it so I know this works, the following is the js you need:

$(function () {
    $('#sample2 ul').each(function () {
        $(this).parent().children('a').eq(0).hover(function () {
            $(this).parent().children('ul').show(100);
            }, function () {
            $(this).parent().children('ul').hide(100);
        });
    });
});

Upvotes: 1

thecodeparadox
thecodeparadox

Reputation: 87073

$('#sample2 > li').hover(
function() {
   // show
   $('ul', this).show(100);
},
function() {
  // hide
  $('ul', this).hide(100);
});

DEMO

Upvotes: 0

Curtis
Curtis

Reputation: 103388

You really don't need jquery for this. A bit of simple CSS will get the desired results:

​ul#sample2 li ul
{
    display:none;
}
​ul#sample2 li:hover ul
{
    display:block;
}​​​

-- SEE DEMO --

Edit: Here's a 3-level example:

-- 3 LEVEL DEMO --

Upvotes: 1

#sample2 ul means get the <UL> element that is a child of the element with ID sample2.

What you are looking for is ul#sample2 as a selector, which means get the <UL> element that has the ID sample2

Upvotes: 1

Related Questions