'jQuery: trouble selecting parent children

I have:

heading
submenu
heading
submenu

submenus are hidden by default. When clicking on a heading, I want to display its submenu and hide the other submenus if they are displaying.

I have inherited Beaver Builder/WordPress so the code is bloated unfortunately.

I'm looking to toggle #ftr-menu-company.footer-text-links when clicking #ftr-hdr-company and hide #ftr-menu-product.footer-text-links if it is open.

On clicking either #ftr-hdr-company or #ftr-hdr-product I'd like to toggleClass("hideBlock") on .footer-text-links children of selfs parent, i.e. the .footer-text-links in the same .fl-col block & then addClass("hide-block") on all other .footer-text-links.

This is not producing any effect.

I am not sure if I can actually perform $(self).parent().children(".footer-text-links").toggleClass("hide-block").

Help appreciated.

$(document).ready(function(){
  $("#ftr-hdr-company").click(function() {
      showSubMenu(self);
  });
  $("#ftr-hdr-product").click(function() {
      showSubMenu(self);
  });
})

function showSubMenu(self) {
    $(".footer-text-links")
      .not($(self).parent().children(".footer-text-links").toggleClass("hide-block"))
    .addClass("hide-block");
}
    #ftr-menu-company.hide-block, #ftr-menu-product.hide-block {display: none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fl-col fl-node-ryu3gqwa2ojf fl-col-small">
    <div class="fl-col-content fl-node-content">
        <div id="ftr-hdr-company" class="fl-module fl-module-heading fl-node-j9orzxfg21dv">
            <div class="fl-module-content fl-node-content geot-module">
                <h4 class="fl-heading"><span class="fl-heading-text">Company</span></h4>
            </div>
        </div>
        <div id="ftr-menu-company"
            class="fl-module fl-module-menu fl-node-2lgy79joxciq footer-text-links hide-block">
            <div class="fl-module-content fl-node-content">
                <div class="fl-menu">
                    <div class="fl-clear"></div>
                    <nav>
                        <ul>
                            <li><a href="#">About Us</a></li>
                            <li><a href="#">Careers</a></li>
                            <li><a href="#">Enterprise</a></li>
                            <li><a href="#">Customers</a></li>
                            <li><a href="#">Partner Program</a></li>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
    <div class="fl-col fl-node-bmnv7hcwkr6t fl-col-small">
        <div class="fl-col-content fl-node-content">
            <div id="ftr-hdr-product" class="fl-module fl-module-heading fl-node-086d9leqrmbp">
                <div class="fl-module-content fl-node-content">
                    <h4 class="fl-heading"><span class="fl-heading-text">Product</span></h4>
                </div>
            </div>
            <div id="ftr-menu-product" class="fl-module fl-module-menu footer-text-links hide-block">
                <div class="fl-module-content fl-node-content">
                    <div class="fl-menu">
                        <div class="fl-clear"></div>
                        <nav>
                            <ul>
                                <li><a href="#">Features</a></li>
                                <li><a href="#">How It Works</a></li>
                                <li><a href="#">Templates</a></li>
                                <li><a href="#">Industries</a></li>
                                <li><a href="#">Use Cases</a></li>
                            </ul>
                        </nav>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


Solution 1:[1]

  • Don't use IDs if you're already using classes
  • Use jQuery's .closest() to refer to a closest parent (or self) before than traversing back using .find() in search for a child
  • Use .toggleClass() to toggle the class
  • Use just .hide-block { display: none; } in CSS
  • Use just $(".fl-module-heading").on("click", showSubMenu); and then use this in your function as a reference to your clicked Event currentTarget Element (the button)

function showSubMenu() {
  const $menuAll = $(".fl-col-content").find(".fl-module-menu");
  const $menu = $(this).closest(".fl-col-content").find(".fl-module-menu");
  $menuAll.not($menu).addClass("hide-block"); // Hide all but target menu
  $menu.toggleClass("hide-block"); // Toggle target menu
}

jQuery($ => { // DOM is Ready and $ alias in scope
  $(".fl-module-heading").on("click", showSubMenu);
});
.hide-block { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fl-col fl-node-ryu3gqwa2ojf fl-col-small">
  <div class="fl-col-content fl-node-content">
    <div id="ftr-hdr-company" class="fl-module fl-module-heading fl-node-j9orzxfg21dv">
      <div class="fl-module-content fl-node-content geot-module">
        <h4 class="fl-heading"><span class="fl-heading-text">Company</span></h4>
      </div>
    </div>
    <div id="ftr-menu-company" class="fl-module fl-module-menu fl-node-2lgy79joxciq footer-text-links hide-block">
      <div class="fl-module-content fl-node-content">
        <div class="fl-menu">
          <div class="fl-clear"></div>
          <nav>
            <ul>
              <li><a href="#">About Us</a></li>
              <li><a href="#">Careers</a></li>
              <li><a href="#">Enterprise</a></li>
              <li><a href="#">Customers</a></li>
              <li><a href="#">Partner Program</a></li>
            </ul>
          </nav>
        </div>
      </div>
    </div>
  </div>
  <div class="fl-col fl-node-bmnv7hcwkr6t fl-col-small">
    <div class="fl-col-content fl-node-content">
      <div id="ftr-hdr-product" class="fl-module fl-module-heading fl-node-086d9leqrmbp">
        <div class="fl-module-content fl-node-content">
          <h4 class="fl-heading"><span class="fl-heading-text">Product</span></h4>
        </div>
      </div>
      <div id="ftr-menu-product" class="fl-module fl-module-menu footer-text-links hide-block">
        <div class="fl-module-content fl-node-content">
          <div class="fl-menu">
            <div class="fl-clear"></div>
            <nav>
              <ul>
                <li><a href="#">Features</a></li>
                <li><a href="#">How It Works</a></li>
                <li><a href="#">Templates</a></li>
                <li><a href="#">Industries</a></li>
                <li><a href="#">Use Cases</a></li>
              </ul>
            </nav>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

Solution 2:[2]

The easiest way to do that is adding a new attribute to the div that you want to toggle.

I added new attribute which name is data-target to your fl-module divs. So, you can easily define your real target about that div in the Javascript part.

The another problem in your code was self. To define the element that has action, you need to use this. I changed that part and also I made some improvements and simplifications in your Jquery code.

$(document).ready(function(){
  $("div[id^='ftr-hdr-']").on('click',function() {
      showSubMenu($(this));
  });
})

function showSubMenu(evt) {
  $("div.fl-module:not([class*='hide-block'])").addClass("hide-block"); //add hide-block to all fl-modules if it has not already one.
  $(evt.attr('data-target')).toggleClass("hide-block");
}
#ftr-menu-company.hide-block, #ftr-menu-product.hide-block {display: none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fl-col fl-node-ryu3gqwa2ojf fl-col-small">
    <div class="fl-col-content fl-node-content">
        <div id="ftr-hdr-company" data-target="#ftr-menu-company" class="fl-module fl-module-heading fl-node-j9orzxfg21dv">
            <div class="fl-module-content fl-node-content geot-module">
                <h4 class="fl-heading"><span class="fl-heading-text">Company</span></h4>
            </div>
        </div>
        <div id="ftr-menu-company"
            class="fl-module fl-module-menu fl-node-2lgy79joxciq footer-text-links hide-block">
            <div class="fl-module-content fl-node-content">
                <div class="fl-menu">
                    <div class="fl-clear"></div>
                    <nav>
                        <ul>
                            <li><a href="#">About Us</a></li>
                            <li><a href="#">Careers</a></li>
                            <li><a href="#">Enterprise</a></li>
                            <li><a href="#">Customers</a></li>
                            <li><a href="#">Partner Program</a></li>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
    <div class="fl-col fl-node-bmnv7hcwkr6t fl-col-small">
        <div class="fl-col-content fl-node-content">
            <div id="ftr-hdr-product" data-target="#ftr-menu-product" class="fl-module fl-module-heading fl-node-086d9leqrmbp">
                <div class="fl-module-content fl-node-content">
                    <h4 class="fl-heading"><span class="fl-heading-text">Product</span></h4>
                </div>
            </div>
            <div id="ftr-menu-product" class="fl-module fl-module-menu footer-text-links hide-block">
                <div class="fl-module-content fl-node-content">
                    <div class="fl-menu">
                        <div class="fl-clear"></div>
                        <nav>
                            <ul>
                                <li><a href="#">Features</a></li>
                                <li><a href="#">How It Works</a></li>
                                <li><a href="#">Templates</a></li>
                                <li><a href="#">Industries</a></li>
                                <li><a href="#">Use Cases</a></li>
                            </ul>
                        </nav>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Roko C. Buljan
Solution 2