Andrew Paton
Andrew Paton

Reputation: 25

Keep Accordion Sub-menu Open on Page Change in Custom WordPress Theme

I have a client site that requires the side menu to act like an accordion with the sub-menu's dropping down after the parent is clicked and staying open while the parent or any of the sub-menu's is active. The menu is created in PHP with the content for the buttons taken from the service section.

The menu is part of the custom theme and has been inserted into several page templates. As is part of the theme I would like to avoid changing the template php code. (not sure how often the theme will be updated) I have tried css and jQuery but so far have only managed to keep the sub-menu open briefly after the onclick then disappears when page loads.

You can see the site at https://www.birchandco.com - There is a hover state at the moment so that visitors can navigate. This would be removed once is working properly with an onclick.

PHP Template:

<div class="home_services">
    <?php 
        $ser= new WP_Query(array(
            'post_type'=>'service',
            'posts_per_page' => -1, 
            'orderby' => 'name',
            'order' => 'ASC',                                   
            'meta_query' => array(
                array(
                    'key' => '_is_ns_featured_post',
                    'value' => 'yes',
                )
            )                                   
        ));

    ?>
    <ul class="service_list">
        <?php 
            if($ser->have_posts()) :
                while($ser->have_posts())  : $ser->the_post();
        ?>
        <li class="item">
            <a href="<?php the_permalink(); ?>"><?php the_title();?> <i class="fa fa-angle-double-right" aria-hidden="true"></i></a>
            <?php if(get_the_terms(get_the_ID() , 'service_category')[0]->term_id) {?>
                <ul class="submenu">
                    <?php
                        $args = array(
                            'post_type' =>'service',                                                    
                            'orderby' => 'name',
                            'order' => 'ASC',                                                                                       
                            'post__not_in' => array(get_the_ID()),
                            'tax_query' => array(
                                array(                      
                                    'taxonomy' => 'service_category',
                                    'field' => 'term_id',                                                       
                                    'terms' => get_the_terms(get_the_ID() , 'service_category')[0]->term_id
                                )
                            )
                        );
                        $query = new WP_Query( $args ); 
                        $loop = new WP_Query( $args );
                        if( $loop->have_posts() ): 
                            while ( $loop->have_posts() ) : $loop->the_post();
                        ?>
                        <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
                        <?php
                        endwhile; wp_reset_postdata();
                        endif;
                        ?>
                </ul>           
            <?php } ?>
        </li>
        <?php
        endwhile;
        wp_reset_postdata(); 
        endif;
        ?>
    </ul>

</div>

CSS

This is the CSS for the current hover state for the submenu

.home_services ul.service_list > li:hover ul.submenu{
display: block;
opacity:1;
visibility:visible;}

JQuery

This is the code that I managed to get to work but it only toggles the sub-menu. Once the onclick event has been executed and the page loads then the sub-menu disappears.

jQuery(document).ready(function($){
var body = $('body');
$('.home_services ul.service_list li a').on('click', 
function(event){
    event.preventDefault();
    // create accordion variables
    var accordion = $(this);
    var accordionContent = accordion.next('.home_services 
 ul.service_list > li ul.submenu');

    // toggle accordion link open class
    accordion.toggleClass("open");
    // toggle accordion content
    accordionContent.slideToggle(250);

});
});

Any help will be most appreciated.

I have seen a possible jquery solution but I am not sure how to apply the below code to my situation. If you can help it would be very much appreciated.

$('.home_services ul.service_list li a').click(function(e){
  ... 

  localStorage.setItem("activeSubMenu", $(this).text());
  });
  On page load, read the localStorage and expand the menu (if found):
  $(document).ready(function(){
var activeItem = localStorage.getItem("activeSubMenu");
if(activeItem){
    $('.home_services ul.service_list li a').filter(function() {
        return $(this).text() == activeItem;
    }).slideToggle();
 }
 });

Upvotes: 0

Views: 2211

Answers (3)

Andrew Paton
Andrew Paton

Reputation: 25

I managed to work out a solution to keeping the sub-menus open on a page change. I removed the PHP code for the existing menu and replaced it with

`<?php //echo do_shortcode("[widget id=nav_menu-3]"); ?>` 

This [widget id=nav_menu-3] shortcode is created via a widget shortcode creator plugin. I used the WordPress menu system to structure the menu then accessed the menu via the navigation Menu widget and added it to the shortcode section so to create a shortcode for the widget. The above code lets you add shortcodes to a PHP template.

This then enabled me to add the WordPress menu to the custom page templates. The next step was to style the menu so it looks like the original menu then via CSS target the current menu item, parent and sub-menu so the sub-menu stays open when the page changes. See code below

`/*--- show or hide sub navs based on the parent menu item or the current menu item
----------------------------------------------- */

.widget_nav_menu ul li.current-menu-item ul.sub-menu {display:block;}
.widget_nav_menu ul li.current-menu-item ul.sub-menu li ul.sub-menu 
{display:none;}

.widget_nav_menu ul li.current-menu-parent ul.sub-menu {display:block;}
.widget_nav_menu ul li.current-menu-parent ul.sub-menu li ul.sub-menu 
{display:none;}
.widget_nav_menu ul li.current-menu-parent ul.sub-menu li.current-menu-item 
ul.sub-menu {display:block;}

.widget_nav_menu ul li.current-menu-parent ul.sub-menu li.current-menu-item 
ul.sub-menu {display:block;}
.widget_nav_menu ul li.current-menu-parent ul.sub-menu li.current-menu-item 
ul.sub-menu li ul.sub-menu {display:none;}`

After that, I added a pseudo-element (double arrow) to the parent to indicate there are sub-menus.

`/*Sub-Menus Pseudo Element - Add to Customise Header
--------------------------------------------- */

ul#menu-services.menu li a:after {
    content: '»';
    font-size: 31px;
    float: right;
  transform: rotate(90deg); -- Turns arrows around so point downwards.
}`

Upvotes: 1

armadadrive
armadadrive

Reputation: 981

On page load, test to see if the URL includes one of the paths that your accordion links to. If so, open that accordion. Something like this:


(function($) {

  $(document).ready(function() {

    // Get the current path (for instance, "/service/contesting-a-will-2/")
    var pathName = window.location.pathname;

    // This is a bit complex, but we're concatenating the pathName variable
    // into your selector so we can find a match and toggle the "open" class
    $('.home_services ul.service_list li a[href*="' + pathName + '"]').toggleClass('open');
  });

})(jQuery);

Note that I haven't tested this, but the general idea is just to match the href attribute from the accordion to the pathname variable we made out of the URL and then open that accordion item. The addition of the [href*=... means "select all tags that contain" and we then pass in the path we got from window.location.pathname.

All things being equal, this should open the accordion as the page is finishing loading which basically achieves the goal of it "being open" on page load.

Upvotes: 0

armin
armin

Reputation: 306

Not answer to your question. But try

<div class="container">
  <div class="panel-group" id="accordionMenu" role="tablist" aria-multiselectable="true">
    <div class="panel panel-default">
      <div class="panel-heading" role="tab" id="headingOne">
        <h4 class="panel-title">
        <a role="button" data-toggle="collapse" data-parent="#accordionMenu" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
          Menu 0
        </a>
      </h4>
      </div>
      <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
        <div class="panel-body">
          <ul class="nav">
            <li><a href="#">item 1</a></li>
            <li><a href="#">item 2</a></li>
            <li><a href="#">item 3</a></li>
          </ul>
        </div>
      </div>
    </div>
    <div class="panel panel-default">
      <div class="panel-heading" role="tab" id="headingTwo">
        <h4 class="panel-title">
        <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordionMenu" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
          Menu 1
        </a>
      </h4>
      </div>
      <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
        <div class="panel-body">
          <ul class="nav">
            <li><a href="#">item 1</a></li>
            <li><a href="#">item 2</a></li>
            <li><a href="#">item 3</a></li>
            <li><a href="#">item 4</a></li>
          </ul>
        </div>
      </div>
    </div>
    <div class="panel panel-default">
      <div class="panel-heading" role="tab" id="headingThree">
        <h4 class="panel-title">
        <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordionMenu" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
          Menu 2
        </a>
      </h4>
      </div>
      <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree">
        <div class="panel-body">
          <ul class="nav">
            <li><a href="#">item 1</a></li>
            <li><a href="#">item 2</a></li>
            <li><a href="#">item 3</a></li>
            <li><a href="#">item 4</a></li>
          </ul>
        </div>
      </div>
    </div>


    <div class="panel panel-default">
      <div class="panel-heading" role="tab" id="headingFour">
        <h4 class="panel-title">
        <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordionMenu" href="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
          Menu 3
        </a>
      </h4>
      </div>
      <div id="collapseFour" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingFour">
        <div class="panel-body">
          <ul class="nav">
            <li><a href="#">item 1</a></li>
            <li><a href="#">item 2</a></li>
          </ul>
        </div>
      </div>
    </div>

  </div>
</div>

Upvotes: 0

Related Questions