Ryley Ameden
Ryley Ameden

Reputation: 77

jQuery first element of type click

I am working through an issue where I have a menu that is mutli levels deep. I am trying to get it so that if a first level element is clicked (add class .ubermenu-active) it will look for any other first level element with that class and remove it.

$('.ubermenu-item-level-0 span').on('click',function() {
    var target = $('.ubermenu-item-level-0');
    $('.ubermenu li.ubermenu-item-level-0').removeClass('ubermenu-active');
    target.parents('.ubermenu li.ubermenu-item-level-0').toggleClass('ubermenu-active');
});

HTML (mock):

<ul class="ubermenu">
    <li class="ubermenu-item-level-0">
        <a class="ubermenu-target">
            <span class="ubermenu-target-title">Level 1</span>
        </a>
        <ul class="ubermenu-submenu">
            <li class="ubermenu-item-level-1">
                <a class="ubermenu-target">
                    <span class="ubermenu-target-title">Level 2</span>
                </a>
            </li>
            <li class="ubermenu-item-level-1">
                <a class="ubermenu-target">
                    <span class="ubermenu-target-title">Level 2</span>
                </a>
                <ul class="ubermenu-submenu">
                    <li class="ubermenu-item-level-2">
                        <a class="ubermenu-target">
                            <span class="ubermenu-target-title">Level 3</span>
                        </a>
                    </li>
                </ul>
            </li>
        </ul>
        <li class="ubermenu-item-level-0">
            <a class="ubermenu-target">
                <span class="ubermenu-target-title">Level 1</span>
            </a>
        </li>
    </li>
</ul>

Right now if any of the sub elements are clicked the parent closes

Upvotes: 0

Views: 293

Answers (4)

talemyn
talemyn

Reputation: 7950

So, your sample HTML isn't what I expected to see . . . specifically, your second <li class="ubermenu-item-level-0" . . . element is currently showing as a child under the first one, while your description makes it sound like they should be siblings.

For the sake of the solution I'm going to assume that those two lis are supposed to be siblings of each other and that somehow the code got mixed up. :)

So, here's how I would handle it . . .

var sFirstLevelMenuClass = ".ubermenu-item-level-0";
var sActiveMenuClass = "ubermenu-active";
var $firstLevelMenuOptions = $(".ubermenu").find(sFirstLevelMenuClass);

$firstLevelMenuOptions.children("a").children("span").on("click", function() {
    $firstLevelMenuOptions.removeClass(sActiveMenuClass);
    $(this).closest(sFirstLevelMenuClass).addClass(sActiveMenuClass);
});

Basically, I've simplified your logic and fixed one small issue that you had in your jQuery code.


Detailed Explanation

The issue was that when you used $('.ubermenu-item-level-0 span') as your selector for your change event. That translates to "any span element that is a descendant of a ubermenu-item-level-0 element". So, in addition to the spans that are directly under the ubermenu-item-level-0 list items, it was also picking up the ones under the ubermenu-item-level-1 and ubermenu-item-level-2 elements, since they are also descendants.

So, I changed your selector to $firstLevelMenuOptions.children("a").children("span") which translates to "all spans, that are direct children of an a, that is the direct child of an ubermenu-item-level-0 element" (Note: $firstLevelMenuOptions is set to equal $(".ubermenu").find(".ubermenu-active"); through the logic earlier in the code). This stops the selector from picking up the lower level spans.

Outside of that and trimming down some of your selectors to be more efficient, the only other thing that I changed was the flow of how the ubermenu-active class is manipulated. In my solution, there are two steps:

  1. Remove ubermenu-active from ALL ubermenu-item-level-0 elements
  2. Add ubermenu-active to the closest ubermenu-item-level-0 element to the span that was clicked (i.e., $(this))

That basically resets the list and then reselects the appropriate menu item to me active.

Upvotes: 0

johnnyd23
johnnyd23

Reputation: 1705

Currently your target var is selecting all elements with class .ubermenu-item-level-0, so when you toggle the class you're toggling all parent elements. Your target var should be something relative to the element clicked, like var target = $(this).closest('.ubermenu-item-level-0');

Upvotes: 1

zeropsi
zeropsi

Reputation: 694

Without seeing the full HTML, I was going to suggest trying this:

$('.ubermenu-item-level-0 span').on('click',function(e) {
       e.stopPropagation();
       var target = $('.ubermenu-item-level-0');
       $('.ubermenu li.ubermenu-item-level-0').removeClass('ubermenu-active');
       target.parents('.ubermenu li.ubermenu-item-level-0').toggleClass('ubermenu-active');
    });

Upvotes: 0

quirimmo
quirimmo

Reputation: 9988

You can stop the event propagation:

event.stopPropagation()

Upvotes: 0

Related Questions