skip to Main Content

I have a menu with submenu with a structure like this:

<ul>
  <li>
    <a class="navigation-item">Menu Item 1</a>
    <a class="submenu-toggle" />
    <ul class="submenu">
      <li>
        <a class="navigation-item">Submenu Item 1</a>
      </li>
    </ul>
  </li>
</ul>

I want to add a class to submenu-toggle if Submenu Item 1 is selected. How can I find the submenu-toggle in this case?

closest('li') won’ work, this will only find the li after the submenu. closest('li > .submenu-toggle') doesn’t work either because the .submenu-toggle has to be an ancestor of the submenu item. If I could select the correct li, I could then use find('.submenu-toggle'). But how do I select the correct li?

5

Answers


  1. To achieve this, you can traverse the DOM to find the correct li element that contains both the submenu-toggle
    and the selected submenu item.

    $(document).ready(function() {
      // Assuming 'Submenu Item 1' is selected
      $('.submenu .navigation-item').on('click', function() {
        // Find the closest 'li' ancestor that contains the submenu
        var parentLi = $(this).closest('ul.submenu').parent('li');
        
        // Find the 'submenu-toggle' within that 'li'
        var submenuToggle = parentLi.find('.submenu-toggle');
        
        // Add the desired class to the 'submenu-toggle'
        submenuToggle.addClass('active');
      });
    });
    
    Login or Signup to reply.
  2. It is way better to find the root of the context, i.e., the container and do the actions relative to that. In the snippet below I loop the li children of #myul as the roots of the contexts, create a click handler on the .navigation-item which will toggle the active class of submenu-toggle.

    $(function() {
        $("#myul > li").each(function() {
            let that = $(this);
            that.find("a.navigation-item").click(function() {
                that.find("a.submenu-toggle").toggleClass("active");
            });
        });
    });
    .submenu-toggle.active {
        color: green;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <ul id="myul">
      <li>
        <a class="navigation-item">Menu Item 1</a>
        <a class="submenu-toggle">some text</a>
        <ul class="submenu">
          <li>
            <a class="navigation-item">Submenu Item 1</a>
          </li>
        </ul>
      </li>
      <li>
        <a class="navigation-item">Menu Item 2</a>
        <a class="submenu-toggle">some text</a>
        <ul class="submenu">
          <li>
            <a class="navigation-item">Submenu Item 2</a>
          </li>
        </ul>
      </li>
    </ul>
    Login or Signup to reply.
  3. You need to traverse the DOM structure from the selected submenu item up to the parent <li> thaat contains both the submenu and the toggle button. Then, you can find the .submenu-toggle within that parent <li>.

    // Assuming the selected submenu item has a class 'selected'
    
    $('.submenu .navigation-item.selected').parents('li').first().find('> .submenu-toggle').addClass('active');
    
    Login or Signup to reply.
  4. I don’t know how it translates to jquery, but in plain Javascript you can just do:

    event.target.parentElement.querySelector(".submenu-toggle").classList.add("new-class")
    
    Login or Signup to reply.
  5. Regardless of the already above commented approach of mine …

    A real generic one with no jQuery needed, just the closest and the querySelector methods together with css-selectors … yourInnerElementReference.closest('li:has(.submenu-toggle)').querySelector('.submenu-toggle'). Have a look at the functional :has() CSS pseudo-class

    … there is a big chance that the OP does not need any JavaScript based solution at all in order to style the toggle-element. This of cause does not imply that JS is entirely obsolete in order to achieve all of the required menu-behaviors, but I would give even that one a real good try.

    .menu {
      display: inline-block;
      
      li {
        margin: 4px 0;
      }
      > li {
        position: relative;
        margin: 12px 0;
    
        > .toggle {
          position: absolute;
          top: 0;
          right: 0;
        }
      }
    }
    .submenu:has(a:active, a:focus, a:target) {
      + .toggle {
        color: green;
      }
    }
    <ul class="menu">
      <li>
        <a href="#">Menu Item 1</a>
    
        <ul class="submenu">
          <li>
            <a href="#">Submenu Item 1.1</a>
          </li>
          <li>
            <a href="#">Submenu Item 1.2</a>
          </li>
        </ul>
        <div tabindex="0" class="toggle">toggle</div>
      </li>
      <li>
        <a href="#">Menu Item 2</a>
    
        <ul class="submenu">
          <li>
            <a href="#">Submenu Item 2.1</a>
          </li>
          <li>
            <a href="#">Submenu Item 2.2</a>
          </li>
        </ul>
        <div tabindex="0" class="toggle">toggle</div>
      </li>
    </ul>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search