Add active class to menu item

2019-08-30 08:36发布

问题:

Using Bootstrap 4 v6, I have the following navigation:

I'm trying to set the active class on the selected menu item, but nothing I've done has worked.

The closest that I've come is with this code:

$(document).ready(function() {
$('.navbar ul li').click(function(e) {
    $('.navbar ul li.active').removeClass('active');
    var $this = $(this);
    if (!$this.hasClass('active')) {
        $this.addClass('active');
    }
    e.preventDefault();
});
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse fixed-top">
    <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <a class="navbar-brand" href="#">DCH</a>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav ml-auto">
            <li class="nav-item active">
                <a class="nav-link" href="index.php">Home</a>
            </li>
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Feline Diabetes</a>
                <div class="dropdown-menu bg-inverse navbar-inverse">
                    <a class="dropdown-item" href="treatment.php">Treatment</a>
                    <a class="dropdown-item" href="insulin.php">Insulin and Testing</a>
                    <a class="dropdown-item" href="relatedconditions.php">Related Conditions</a>
                </div>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="nutrition.php">Nutrition</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="protocol.php">Protocol</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="links.php">Links</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://diabeticcathelp.com/forum" target="_blank">Forum</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="contact.php">Contact Us</a>
            </li>
        </ul>
    </div>
</nav>

It does change the active class to the clicked menu item, but it does not change the pages. It also doesn't work on the submenu items, though I think that I would need different code to see if those particular items were clicked and I haven't gotten that far. First, I'd like to get past the page switching issue. If I remove the e.preventDefault() call, then the pages shift, but the menu items are not changed to active.

Any ideas on how I might make this work?

Update. I have this working for everything except for the submenus. I'm using the following code, which is adapted from one of the answers in this thread:

$(document).ready(function () {
    var listItems = $('.navbar ul li');

    $.each(listItems, function (key, litem) {
        var aElement = $(this).children(litem)[0];

        if(aElement == document.URL) {
            $(litem).addClass('active');
        }
    });
});

The only thing that I'm missing is the adding active to the submenu items. This code is taking the first child item of .navbar ul li items and doing the comparison to see if I need to add the active class. I know that when I have an li with a class of .nav-item .dropdown that I need to step through the children of the .dropdown-menu, and check there. I'm just struggling to figure out how. I really need to take a JQuery course.

Further edit:

After playing with this for a few hours, I have a solution that works for what I'm trying to do:

var setSubItemParent = false;

$(document).ready(function () {
    var listItems = $('.navbar ul li');

    $.each(listItems, function(key, litem) {
        iterateLinks(litem);
    })
});

function iterateLinks(liItem) {
    var divchildren = $(liItem).children('div');

    setSubItemParent = false;

    /* If there are div children, iterate them */
    if (divchildren.length > 0) {
        iterateLinks(divchildren[0]);

        /* If an item was set and we're in a div, add active to 
           this element as well. */
        if(setSubItemParent) {
            $(liItem).addClass('active');
        }

    }
    else {
        var achildren = $(liItem).children('a');

        /* Run through all a tags and see if they should be active */
        if (achildren.length > 0 ) {
            $.each(achildren, function(key, achild) {
                if (achild.href == document.URL) {
                    $(achild).addClass('active');
                    setSubItemParent = true;
                }
            });
        }
    }
}

The code runs through all of the li elements in the menu and digs further if it finds a div. This probably isn't the most robust solution to the problem, but it does work. I am open to a better solution, however.

回答1:

It should work for you, but this will add active class to the a tag not in li.

$(document).ready(function () {
    var links = $('.navbar ul li a');
    $.each(links, function (key, va) {
        if (va.href == document.URL) {
            $(this).addClass('active');
        }
    });
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse fixed-top">
    <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <a class="navbar-brand" href="#">DCH</a>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav ml-auto">
            <li class="nav-item">
                <a class="nav-link" href="index.php">Home</a>
            </li>
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Feline Diabetes</a>
                <div class="dropdown-menu bg-inverse navbar-inverse">
                    <a class="dropdown-item" href="treatment.php">Treatment</a>
                    <a class="dropdown-item" href="insulin.php">Insulin and Testing</a>
                    <a class="dropdown-item" href="relatedconditions.php">Related Conditions</a>
                </div>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="nutrition.php">Nutrition</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="protocol.php">Protocol</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="links.php">Links</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://diabeticcathelp.com/forum" target="_blank">Forum</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="contact.php">Contact Us</a>
            </li>
        </ul>
    </div>
</nav>



回答2:

Looks like your links load a new php page, so loading them will reset the classes you added in your click handler. You should handle this on the server side in your php code and html templates. For example, in the code for your nutrition.php file, add a variable called something like $nutrition_active set to TRUE. In your nav template you will need to add an if condition for each link that checks for that variable you set for each page:

<li class="nav-item <? if ($nutrition_active) { ?>active<? }?>"><a class="nav-link" href="nutrition.php" >Nutrition</a>


标签: bootstrap-4