Benn Benn - 3 months ago 13
CSS Question

Vertical toggle menu 3rd level parent stay opened. jQuery

I am working on a simple vertical toggle menu but having trouble leaving the first drop level opened when its sub level is clicked. For less confusion here is fiddle , click on "Products" than on "Sites" and products will close.

But if you click on Products and than on Services it does what is needed
which is , close other subs when one is opened.



$('.vtoggle li').each(function(el) {

$(this).find('a').first().attr('href', 'javascript:;').addClass('vtoggler');

});
$('ul.vtoggle > li:has(ul)').addClass("inactive");
$('ul.vtoggle > li:has(ul) ul').css('display', 'none');

$('.vtoggler').click(function() {

var checkElement = $(this).next();

$('.vtoggle li').removeClass('active');
$(this).closest('li').addClass('active').removeClass("inactive");

if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
$(this).closest('li').removeClass('active').addClass('inactive');
checkElement.slideUp('normal');
}

if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {

$('ul.vtoggle ul:visible').slideUp('normal');
checkElement.slideDown('normal');
}

if (checkElement.is('ul')) {
return false;
} else {
return true;
}
});

body {
background: #fff;
}

.vertical ul {
list-style-type: none;
padding: 0;
margin: 0;
display: block;
position: relative;
}

.vertical li {
list-style-type: none;
padding: 0;
margin: 0;
display: block;
float: none;
position: relative;
}

.vertical li a {
display: block;
height: 45px;
line-height: 45px;
padding: 0 10px;
border: 1px solid rgba(0, 0, 0, 0);
border-bottom-color: #eee;
}


/* sub menu */

.vertical ul ul {
display: none;
position: relative;
padding: 0 0 0 20px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="vertical">
<ul class="vtoggle">
<li><a href="#">Home</a></li>
<li><a href="#">Services +</a>
<ul>
<li><a href="#">Service 1</a></li>
<li><a href="#">Service 2</a></li>
<li><a href="#">Service 3</a></li>
</ul>
</li>
<li><a href="#">Products +</a>
<ul>
<li><a href="#">Widgets</a></li>
<li>
<a href="#">Sites +</a>
<ul>
<li><a href="#">Site 1</a></li>
<li><a href="#">Site 2</a></li>
</ul>
</li>
<li><a href="#">Gadgets +</a>
<ul>
<li><a href="#">Gadget 1</a></li>
<li><a href="#">Gadget 2</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Contact</a></li>
</ul>
</nav>




Answer

A soution can be to wrap line into:

    var lastUl = $('ul.vtoggle ul:visible:last');
    if (lastUl.find(this).length == 0) {
        $('ul.vtoggle ul:visible').each(function() {
            if ($(this).find(checkElement).length == 0) {
                $(this).slideUp('normal');
            }
        })
    }

The snippet:

$(function () {
  $('.vtoggle li').each(function (el) {

    $(this).find('a').first().attr('href', 'javascript:;').addClass('vtoggler');

  });
  $('ul.vtoggle > li:has(ul)').addClass("inactive");
  $('ul.vtoggle > li:has(ul) ul').css('display', 'none');

  $('.vtoggler').click(function (e) {

    var checkElement = $(this).next();

    $('.vtoggle li').removeClass('active');
    $(this).closest('li').addClass('active').removeClass("inactive");

    if ((checkElement.is('ul')) && (checkElement.is(':visible'))) {
      $(this).closest('li').removeClass('active').addClass('inactive');
      checkElement.slideUp('normal');
    }

    if ((checkElement.is('ul')) && (!checkElement.is(':visible'))) {

      var lastUl = $('ul.vtoggle ul:visible:last');
      if (lastUl.find(this).length == 0) {
        $('ul.vtoggle ul:visible').each(function() {
          if ($(this).find(checkElement).length == 0) {
            $(this).slideUp('normal');
          }
        })
      }

      checkElement.slideDown('normal');
    }

    if (checkElement.is('ul')) {
      return false;
    } else {
      return true;
    }
  });
});
body {
  background: #fff;
}

.vertical ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: block;
  position: relative;
}

.vertical li {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: block;
  float: none;
  position: relative;
}

.vertical li a {
  display: block;
  height: 45px;
  line-height: 45px;
  padding: 0 10px;
  border: 1px solid rgba(0, 0, 0, 0);
  border-bottom-color: #eee;
}


/* sub menu */

.vertical ul ul {
  display: none;
  position: relative;
  padding: 0 0 0 20px;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>

<nav class="vertical">
    <ul class="vtoggle">
        <li><a href="#">Home</a></li>
        <li><a href="#">Services +</a>
            <ul>
                <li><a href="#">Service 1</a></li>
                <li><a href="#">Service 2</a></li>
                <li><a href="#">Service 3</a></li>
            </ul>
        </li>
        <li><a href="#">Products +</a>
            <ul>
                <li><a href="#">Widgets</a></li>
                <li>
                    <a href="#">Sites +</a>
                    <ul>
                        <li><a href="#">Site 1</a></li>
                        <li><a href="#">Site 2</a></li>
                    </ul>
                </li>
                <li><a href="#">Gadgets +</a>
                    <ul>
                        <li><a href="#">Gadget 1</a></li>
                        <li><a href="#">Gadget 2</a></li>
                    </ul>
                </li>
            </ul>
        </li>
        <li><a href="#">Contact</a></li>
    </ul>
</nav>

Comments