Home > Back-end >  Closest in if statement and parse data in function loop
Closest in if statement and parse data in function loop

Time:02-23

HTML code from menu:

<ul id="sidebarMenu"  data-nav-type="accordion">
    <li >
        <a href="#" ><i ></i>Webadmin</a>
        <ul >
            <li ><a href="#" ><i ></i>tester</a>
                <ul >
                    <li >
                        <a href="#" ><i ></i>tester 2</a>
                        <ul >
                            <li >
                                <a href="/webadmin/config" ><i ></i>Site instellingen</a>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li ><a href="/webadmin/configMenu" ><i ></i>Menu aanpassen</a></li>
        </ul>
    </li>
</ul>

What I want is add a class 'nav-item-expanded nav-item-open' on al related li with class nav-item-submenu.

So if the user is an a page that the menu collapse automatically the sub menus until the link

I have the next code:

This works. But its limited on my script this wil go back for 5 subs. But if the user want to use by example 6 menus the script fails. Sorry for my bad writing: D

$('.nav-item > a.active')
    .closest('.nav-item-submenu')
    .addClass('nav-item-expanded nav-item-open')
    .parent()
    .closest('.nav-item-submenu')
    .addClass('nav-item-expanded nav-item-open')
    .parent()
    .closest('.nav-item-submenu')
    .addClass('nav-item-expanded nav-item-open')
    .parent()
    .closest('.nav-item-submenu')
    .addClass('nav-item-expanded nav-item-open')
    .parent()
    .closest('.nav-item-submenu')
    .addClass('nav-item-expanded nav-item-open')

how can I simplify this code?

Example that I have tried:

var test = function(data = '') {
    if (data === '') {
        data = $('.nav-item > a.active').closest('.nav-item-submenu');
    } else {
        data = data.parent().closest('nav-item-submenu');
    }

    if (data.length > 0) {
        data.addClass('nav-item-expanded nav-item-open');
        test(data);
    }
};

but that's not working.

CodePudding user response:

You can use .parentsUntil() to simplify this. It returns all ancestors up to a point and can filter them. It takes two parameters:

  1. Selector for the final ancestor to stop at.
  2. Selector to filter the ancestors by.

This is almost the opposite of .find() which will traverse descendants instead. However, .find() will always work at any depth, it does not have a stop conditions like .parentsUntil().

A single call to .parentsUntil('#sidebarMenu', '.nav-item-submenu') will return all ancestor elements that you want - the .nav-item-submenu ones. At that point, you can add the classes you want or manipulate them further, if needed.

$('button').on('click', function() {

  $('.nav-item > a.active')
    .parentsUntil('#sidebarMenu', '.nav-item-submenu')
    .addClass('nav-item-expanded nav-item-open');
})
.nav-item-submenu {
  min-height: 50px;
  padding: 5px;
  border: 1px dashed black;
}

.nav-item-expanded {
  border: 2px solid black;
}

.nav-item-open {
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul id="sidebarMenu"  data-nav-type="accordion">
    <li >
        <a href="#" >A</a>
        <ul >
            <li ><a href="#" >B1</a>
                <ul >
                    <li >
                        <a href="#" >C</a>
                        <ul >
                            <li >
                                <a href="#" >D</a>
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li ><a href="#" >B2</a></li>
        </ul>
    </li>
</ul>

<button>Click me</button>

  • Related