Home > front end >  jQuery: trouble selecting parent children
jQuery: trouble selecting parent children

Time:03-31

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 >
    <div >
        <div id="ftr-hdr-company" >
            <div >
                <h4 ><span >Company</span></h4>
            </div>
        </div>
        <div id="ftr-menu-company"
            >
            <div >
                <div >
                    <div ></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 >
        <div >
            <div id="ftr-hdr-product" >
                <div >
                    <h4 ><span >Product</span></h4>
                </div>
            </div>
            <div id="ftr-menu-product" >
                <div >
                    <div >
                        <div ></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>

CodePudding user response:

  • 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 >
  <div >
    <div id="ftr-hdr-company" >
      <div >
        <h4 ><span >Company</span></h4>
      </div>
    </div>
    <div id="ftr-menu-company" >
      <div >
        <div >
          <div ></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 >
    <div >
      <div id="ftr-hdr-product" >
        <div >
          <h4 ><span >Product</span></h4>
        </div>
      </div>
      <div id="ftr-menu-product" >
        <div >
          <div >
            <div ></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>

CodePudding user response:

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 >
    <div >
        <div id="ftr-hdr-company" data-target="#ftr-menu-company" >
            <div >
                <h4 ><span >Company</span></h4>
            </div>
        </div>
        <div id="ftr-menu-company"
            >
            <div >
                <div >
                    <div ></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 >
        <div >
            <div id="ftr-hdr-product" data-target="#ftr-menu-product" >
                <div >
                    <h4 ><span >Product</span></h4>
                </div>
            </div>
            <div id="ftr-menu-product" >
                <div >
                    <div >
                        <div ></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>

  • Related