0

I have a responsive menu three levels deep, and I have some vanilla JavaScript toggling the ul class. It works, but only for the first submenu that appears in the navigation. This is for a WordPress theme, so I have no real control over where or how many submenus there happen to be after handoff.

No jQuery, please.

Here's the markup:

<nav id="site-navigation" class="main-navigation">
    <div id="primary-menu" class="menu">
    <ul>
        <li class="page_item page-item-703"><a href="/blog/">Blog</a></li>
        <li class="page_item page-item-701"><a href="/front-page/">Front Page</a></li>
        <li class="page_item page-item-2"><a href="/sample-page/">Sample Page</a></li>
        <li class="page_item page-item-6 page_item_has_children"><a href="/about/">About The Tests</a><span class="sub-nav-toggle">›</span>
            <ul class='children'>
                <li class="page_item page-item-1133"><a href="/about/page-image-alignment/">Page Image Alignment</a></li>
                <li class="page_item page-item-1134"><a href="/about/page-markup-and-formatting/">Page Markup And Formatting</a></li>
                <li class="page_item page-item-501"><a href="/about/clearing-floats/">Clearing Floats</a></li>
                <li class="page_item page-item-155"><a href="/about/page-with-comments/">Page with comments</a></li>
                <li class="page_item page-item-156"><a href="/about/page-with-comments-disabled/">Page with comments disabled</a></li>
            </ul>
        </li>
        <li class="page_item page-item-174 page_item_has_children"><a href="/level-1/">Level 1</a><span class="sub-nav-toggle">›</span>
            <ul class='children'>
                <li class="page_item page-item-173 page_item_has_children"><a href="/level-1/level-2/">Level 2</a><span class="sub-nav-toggle">›</span>
                    <ul class='children'>
                        <li class="page_item page-item-172"><a href="/level-1/level-2/level-3/">Level 3</a></li>
                        <li class="page_item page-item-746"><a href="/level-1/level-2/level-3a/">Level 3a</a></li>
                        <li class="page_item page-item-748"><a href="/level-1/level-2/level-3b/">Level 3b</a></li>
                    </ul>
                </li>
                <li class="page_item page-item-742"><a href="/level-1/level-2a/">Level 2a</a></li>
                <li class="page_item page-item-744"><a href="/level-1/level-2b/">Level 2b</a></li>
            </ul>
        </li>
        <li class="page_item page-item-146"><a href="/lorem-ipsum/">Lorem Ipsum</a></li>
        <li class="page_item page-item-733"><a href="/page-a/">Page A</a></li>
        <li class="page_item page-item-735"><a href="/page-b/">Page B</a></li>
    </ul>
    </div>
</nav><!-- #site-navigation -->

And here's the script:

document.querySelector('.sub-nav-toggle').onclick = function(){
     document.getElementsByClassName('children')[0].classList.toggle("active");
};

Like I said, this only toggles the first submenu that appears in the nav. The .active class changes the max-height to show the submenu.

I'm using this script to add a span with a class of .sub-nav-toggle to the li:

/**
* Add toggles to menu items that have submenus.
*/
var x = document.body.querySelectorAll('.page_item_has_children > a');
var index = 0;
for (index = 0; index < x.length; index++) {
     var navArrow = document.createElement('span');
     navArrow.className = 'sub-nav-toggle';
     navArrow.innerHTML = '&rsaquo;';
     x[index].parentNode.insertBefore(navArrow, x[index].nextSibling);
}

I know how to do this with jQuery, but I don't want to load all of jQuery to do this one task.

BSMP
  • 4,596
  • 8
  • 33
  • 44
Mike Jandreau
  • 392
  • 3
  • 16

1 Answers1

0

The problem is you using jQuery logic in non-jquery script:

document.querySelector('.sub-nav-toggle').onclick = function(){
   document.getElementsByClassName('children')[0].classList.toggle("active");
};

First of all document.querySelector('.sub-nav-toggle') will return just one first element with .sub-nav-toggle.

You need to use querySelectorAll that will return array of .sub-nav-toggle elements.

Then you need to set onclick function for each of that elements.

Second error is document.getElementsByClassName('children')[0].classList.toggle("active");. This will toggle only first .children element. You need to find .children in parent of clicked .sub-nav-toggle.

Working demo: https://jsfiddle.net/8ewua0aL/2/

Or snippet below:

var x = document.body.querySelectorAll('.page_item_has_children > a');
var index = 0;
for (index = 0; index < x.length; index++) {
 var navArrow = document.createElement('span');
 navArrow.className = 'sub-nav-toggle';
 navArrow.innerHTML = '<b>[toggle]</b>';
 x[index].parentNode.insertBefore(navArrow, x[index].nextSibling);
}

var elements = document.querySelectorAll('.sub-nav-toggle');

for(var i in elements) {
 if(elements.hasOwnProperty(i)) {
  elements[i].onclick = function() {
   this.parentElement.querySelector('.children').classList.toggle("active");
  }
 }
}
.active, .active a {
 color: red;
}
.sub-nav-toggle {
  cursor: pointer;
}
<nav id="site-navigation" class="main-navigation">
    <div id="primary-menu" class="menu">
    <ul>
        <li class="page_item page-item-703"><a href="/blog/">Blog</a></li>
        <li class="page_item page-item-701"><a href="/front-page/">Front Page</a></li>
        <li class="page_item page-item-2"><a href="/sample-page/">Sample Page</a></li>
        <li class="page_item page-item-6 page_item_has_children"><a href="/about/">About The Tests</a>
            <ul class='children'>
                <li class="page_item page-item-1133"><a href="/about/page-image-alignment/">Page Image Alignment</a></li>
                <li class="page_item page-item-1134"><a href="/about/page-markup-and-formatting/">Page Markup And Formatting</a></li>
                <li class="page_item page-item-501"><a href="/about/clearing-floats/">Clearing Floats</a></li>
                <li class="page_item page-item-155"><a href="/about/page-with-comments/">Page with comments</a></li>
                <li class="page_item page-item-156"><a href="/about/page-with-comments-disabled/">Page with comments disabled</a></li>
            </ul>
        </li>
        <li class="page_item page-item-174 page_item_has_children"><a href="/level-1/">Level 1</a>
            <ul class='children'>
                <li class="page_item page-item-173 page_item_has_children"><a href="/level-1/level-2/">Level 2</a>
                    <ul class='children'>
                        <li class="page_item page-item-172"><a href="/level-1/level-2/level-3/">Level 3</a></li>
                        <li class="page_item page-item-746"><a href="/level-1/level-2/level-3a/">Level 3a</a></li>
                        <li class="page_item page-item-748"><a href="/level-1/level-2/level-3b/">Level 3b</a></li>
                    </ul>
                </li>
                <li class="page_item page-item-742"><a href="/level-1/level-2a/">Level 2a</a></li>
                <li class="page_item page-item-744"><a href="/level-1/level-2b/">Level 2b</a></li>
            </ul>
        </li>
        <li class="page_item page-item-146"><a href="/lorem-ipsum/">Lorem Ipsum</a></li>
        <li class="page_item page-item-733"><a href="/page-a/">Page A</a></li>
        <li class="page_item page-item-735"><a href="/page-b/">Page B</a></li>
    </ul>
    </div>
</nav>
Sergey Khalitov
  • 987
  • 7
  • 17