0

What I'm trying to achieve at first is to test if an "li" has an "ul" nested within, and if so, to show the nested "ul" on click. this is working well; HOWEVER, the if statement is returning true for every "li" not just the ones that have a child "ul". this means the links without submenus don't work, since e.preventDefault() gets invoked.

Thanks for help!

$('.main_nav').on('click', 'a', function(e) {
		if( $(this).parent().has('ul') ) {
			e.preventDefault();
			$(this).parent().children('ul').toggle( 800, 'easeOutQuint', function() {
				 $(this).closest('li').toggleClass('open dropdown');
    		}).closest('li').siblings('.open').toggleClass('open dropdown').children('ul').hide('fast');
		}
	});
 <nav class="main_nav" role="navigation" aria-label="Primary Menu">
        <ul id="menu-main" class="menu"><li id="menu-item-7" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-4 current_page_item menu-item-7"><a href="http://projectbiketech.dev/">Home</a></li>
<li id="menu-item-22" class="dropdown menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-22"><a href="http://projectbiketech.dev/about/">About</a>
<ul class="sub-menu">
	<li id="menu-item-61" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-61"><a href="http://projectbiketech.dev/about/team/">Team</a></li>
	<li id="menu-item-60" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-60"><a href="http://projectbiketech.dev/about/board-of-directors/">Board of Directors</a></li>
	<li id="menu-item-59" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-59"><a href="http://projectbiketech.dev/about/advisory-board/">Advisory Board</a></li>
	<li id="menu-item-58" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-58"><a href="http://projectbiketech.dev/about/friends-of-pbt/">Friends of PBT</a></li>
</ul>
</li>
<li id="menu-item-25" class="dropdown menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-25"><a href="http://projectbiketech.dev/programs/">Programs</a>
<ul class="sub-menu">
	<li id="menu-item-65" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-65"><a href="http://projectbiketech.dev/programs/bike-tech-in-school/">Bike Tech In School</a></li>
</ul>
</li>
<li id="menu-item-28" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-28"><a href="http://projectbiketech.dev/chapters/">Chapters</a></li>
<li id="menu-item-31" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-31"><a href="http://projectbiketech.dev/media/">Media</a></li>
<li id="menu-item-34" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-34"><a href="http://projectbiketech.dev/support/">Support</a></li>
<li id="menu-item-37" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-37"><a href="http://projectbiketech.dev/contact/">Contact</a></li>
</ul>    </nav><!-- .main_navigation -->

2
  • You are using jQuery has selector wrongly. Guess you want to check if parent contains any nested UL? You would have to explain what behavior you want to achieve: once you click and toggle submenu, what happens if you click other links, or same link? You are also mixing script and styles, adding styles, but hiding elements... think you started wrong way in general. Commented Sep 6, 2016 at 20:02
  • Possible duplicate of jQuery if has() selector do stuff Commented Sep 6, 2016 at 20:10

2 Answers 2

2

The basic way to toggle submenu via script would be:

$('a').on('click', function(e){
    var thisLink = $(this);
    var subMenu = thisLink.siblings('ul');
    if( subMenu.length>0 ) {
    	subMenu.slideToggle();
        return false;
    };
});
ul ul {
    display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a>
        <ul>
            <li><a href="#">Team</a></li>
            <li><a href="#">Directors</a></li>
        </ul>
    </li>
    <li><a href="#">Programs</a>
        <ul>
            <li><a href="#">Subitem 1</a></li>
            <li><a href="#">Subitem 2</a></li>
        </ul>
    </li>
</ul>

The jQuery has selector you tried to use has something else to do:

Description: Reduce the set of matched elements to those that have a descendant that matches the selector or DOM element.

If you want to check if element is a parent of some ul, than you should do it this way:

 if( $element.find('ul').length>0 ) { .. do .. };

For your specific case, you would use:

 if( $(this).parent().find('ul').length>0 ) { .. it has some nested list ..};
Sign up to request clarification or add additional context in comments.

Comments

0

You have the problem of a truthy value being populated into your conditional. has() does not return a boolean value, it returns a filtered jQuery collection based on the selector specified. You can use length to investigate the size of collection (which could be 0).

Example:

if( $(this).parent().has('ul').length > 0 ) {

You might, as an alternative, consider specifying a different class to use to enforce this behavior as well. That would allow you to only attach this on click "override" behavior on those particular a tags of the given class. This would perform better than repeated DOM queries and traversal.

1 Comment

Thanks for such quick and correct responses! I changed .has('ul') to .has('ul').length > 0 , but the .find method worked as well. thanks again!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.