0

I have the the following in my script tag. However, whenever I click the on test.php or test2.php li links, I am not redirected to the respective pages. However, the active class changes from the index.php file to the test.php or test2.php file depending on which link has been clicked but I am not directed to the page. I attempted to the solutions in the following links, but now of them produce the desired result that I want, which is to redirect me to the page clicked and update the active class to the li element.

How to change active class while click to another link in bootstrap use jquery?

Active link after click

Whenever I uncomment this line e.preventDefault(), I am able to navigate to the link that have been click but the active class is not updated to the the li elememnt clicked, but when the said line is commented, I am not able to navigate to the page clicked, instead, the active class is updated on the li element clicked.

<div class="menu">
    <ul class="list">
        <li class="header">MAIN NAVIGATION</li>
        <li class="active">
            <a href="index.php">
                <i class="material-icons">home</i>
                <span>Home</span>
            </a>
        </li>
        <li class="">
            <a href="test.php">
                <i class="material-icons">group</i>
                <span>Test</span>
            </a>
        </li>
        <li class="">
            <a href="test2.php">
                <i class="material-icons">people</i>
                <span>Test2</span>
            </a>
        </li>
    </ul>
 </div>

And the script code:

$(document).ready(function () {
    $('.menu .list a').click(function(e) {

        $('.menu li.active').removeClass('active');

        var $parent = $(this).parent();
        $parent.addClass('active');
        e.preventDefault();
    });
});

The contents of test.php are as follows:

<body class="theme-red">
    <nav class="navbar">
        <?php include_once('navbar.html'); ?>
    </nav>
    <section>
        <aside id="leftsidebar" class="sidebar">
            <?php include_once('left-side-bar.html');?>
        </aside>
    </section>

    <section class="content">
        <div class="container-fluid">
            <div class="row clearfix">
                <table id="tbl-users" class="table">
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>Name</th>
                        </tr>
                    </thead>
                    <tfoot>
                        <tr>
                            <th>ID</th>
                            <th>Name</th>
                        </tr>
                    </tfoot>
                    <tbody>
                    <?php
                        $accounts = get_details();
                        foreach($accounts as $acc){
                    ?>
                        <tr>
                            <td><?php echo $acc['id']; ?></td>
                            <td><?php echo $acc['name']; ?></td>
                        </tr>
                    <?php
                        }
                    ?>
                    </tbody>
                </table>
            </div>
        </div>
    </section>
</body>
Andre Reid
  • 95
  • 2
  • 11
  • 2
    I think you need to apply the active class using PHP. If you uncomment `e.preventDefault();` and click the link the page will refresh and any frontend changes you made with jQuery will be reset. – dom_ahdigital Dec 12 '17 at 16:10
  • 1
    Possible duplicate of [Add ".active" class to the current page's link in a menu using jQuery or PHP](https://stackoverflow.com/questions/13349046/add-active-class-to-the-current-pages-link-in-a-menu-using-jquery-or-php) – dom_ahdigital Dec 12 '17 at 16:10
  • If you could, add the code for your test.php or test2.php to know exactly what is it . –  Dec 12 '17 at 16:40
  • @ Highdef the code has been added for test.php – Andre Reid Dec 12 '17 at 17:37

5 Answers5

2

Why is the problem arising?

The problem arises that, when you use e.preventDefault() on click of anchor tag, the default behaviour is to redirect the page and that's why the page doesn't load but the active class gets added. But when you don't use e.preventDefault(), the page redirects immediately and the change you did happen but before it was redirected and not for the new page(which could be redirected current page or some other page), that's why you can't see the class active added to it.

.

How to fix the problem?

Well, there are a couple of ways to go about it. I'd say that from the test.php or test2.php return a value, which you can validate against the javascript with if-else conditions, if the value matches you make that li class as active.

Here's the changes you need to make:

Add a span on each of your pages to which you have hyperlinked i.e test.php, test2.php, etc. having text the same as your hyperlink in the anchor tag so for test.php add a span as:

<span id="curpage" style="display:none;">test.php</span>

Then, add a script at the end of your body tag (you may be able to add this script in a seperate file and include in all of your php files using <?php include(".."); ?> :

$('a[href=\"' + $("#curpage").text() + '\"]').parent().addClass("active");

Here's a sample code, that you can try and implement. Make 2 files in the same directory named as a.html having the code:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
  <span id="curpage" style="display:none;">a.html</span>
  <div class="menu">
  <li><a href="b.html">1</a></li>
  <li><a href="a.html">2</a></li>
</div>
<script>
  $('a[href=\"' + $("#curpage").text() + '\"]').parent().css("color","red");
</script>
</body>
</html>

And b.html having the code:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
  <span id="curpage" style="display:none;">b.html</span>
  <div class="menu">
  <li><a href="b.html">1</a></li>
  <li><a href="a.html">2</a></li>
</div>
<script>
  $('a[href=\"' + $("#curpage").text() + '\"]').parent().css("color","red");
  </script>
  </body>
</html>

And now when you change the pages by clicking the link, you can see how the color of bullet changes.

  • If you could demonstrate your solution you'll earn my vote :) – UncaughtTypeError Dec 12 '17 at 16:35
  • @UncaughtTypeError I could if I knew what exactly the OP'S test.php code includes or if it redirects back or is another page with a navigation bar as such. If it were another page with the navigation bar a simpler solution would be to have the li just be active on that page for that particular option. –  Dec 12 '17 at 16:36
  • Consider writing up a quick jQuery solution anyway. It may still prove to be helpful to others experiencing the same issue or a similar one. – UncaughtTypeError Dec 12 '17 at 16:45
  • test.php does not contain any links to allow the user to redirect back. The link to navigate to each respective page is in one component say left-sideBar.html which is included in the test.php and test2.php file. – Andre Reid Dec 12 '17 at 16:49
  • @AndreReid Could you just add the code of test.php eitherway, because if it isn't a script then the solution might be more simple than thought. –  Dec 12 '17 at 16:50
  • @UncaughtTypeError Updated the answer. –  Dec 12 '17 at 18:01
  • @AndreReid Updated. –  Dec 12 '17 at 18:01
  • @Highdef this solution looks feasible but it does not produce the required results – Andre Reid Dec 12 '17 at 18:32
  • @AndreReid I tried it by creating some sample webpages and it does. –  Dec 12 '17 at 18:33
  • I am going to double check your solution – Andre Reid Dec 12 '17 at 18:34
  • @AndreReid Do include the span in each of your individual pages and add the script in the end of your body. –  Dec 12 '17 at 18:35
  • @Highdef Yes I did – Andre Reid Dec 12 '17 at 18:37
  • @AndreReid I'll add a sample code and you can try to see how it works. –  Dec 12 '17 at 18:38
  • @AndreReid I have updated the sample code, check it out. –  Dec 12 '17 at 18:43
  • @Highdef I tested you solution, It works but my implementation is a bit different in that, I have a separate component which contains the navigation link which would then be included into a.html and b.html. And on subsequent click of links 1 and 2 I am redirected to that specific page. – Andre Reid Dec 12 '17 at 18:55
  • @AndreReid It doesn't matter as long as the navigation code included in every page using php is the same. I tried it modifying it and including the file as php as well. –  Dec 12 '17 at 18:58
  • @ Highdef I revisited your solution I was able to get it to wok. – Andre Reid Dec 12 '17 at 19:16
  • @AndreReid Good to know :) –  Dec 12 '17 at 19:17
  • Good to see your persistence has paid off, you went above and beyond the call of duty here. If I could give you another upvote for effort I would :) Keep up the good work man, you have a fan. – UncaughtTypeError Dec 12 '17 at 19:30
0

You should know e.preventDefault() will prevent default behavior of that object which called on it (redirect in this case). So you are preventing your application from redirect to that href you specified.

You can change your function code like this:

$(document).ready(function () {
    $('.menu .list a').click(function(e) {

        $('.menu li.active').removeClass('active');

        var $parent = $(this).parent();
        $parent.addClass('active');
        e.preventDefault();

        //Here is needed change
        location.href = $(this).attr('href');
    });
});

Edit 1: So you can work like this approach:

1) Specify a class name for each li tag

2) Send the class name that must has active class after redirection and page load

3) Read the passed class name from url and add/remove to/from your li tags

So your html code will be as following:

<div class="menu">
    <ul class="list">
        <li class="header">MAIN NAVIGATION</li>
        <li class="home active">
            <a href="index.php">
                <i class="material-icons">home</i>
                <span>Home</span>
            </a>
        </li>
        <li class="group">
            <a href="test.php">
                <i class="material-icons">group</i>
                <span>Test</span>
            </a>
        </li>
        <li class="people">
            <a href="test2.php">
                <i class="material-icons">people</i>
                <span>Test2</span>
            </a>
        </li>
    </ul>
 </div>

If you need to script code according to this solution which I explained, so I will update my answer.

Edit 2: You need to have below script codes in your file:

function setActiveClass() {
    //Remove active class from all li tags
    $('.menu li.active').removeClass('active');
    //Find current url
    var url = $(location).attr('href');

    if (url.contains("activeClass")) {
        //Find the index of active class in url
        var start = url.indexOf("#activeClass");
        //Add 6 unit to start index because of the longest class name is people which has 6 character
        var end = start + 6;
        //Fetch passed class name from url
        var className = url.substring(start, end);

        //Add active class corresponding to passed class name
        if(className.contains("home"))
            $(".home").addClass('active');
        else if(className.contains("group"))
            $(".group").addClass('active');
        else
            $(".people").addClass('active');
    } else {
        //Add active class for default mode (when we have not any redirect yet)
        $("#defaultLiTag").addClass('active');
    }
}

$(document).ready(function () {
    //Call the function
    setActiveClass();

    $('.menu .list a').click(function(e) {
        e.preventDefault();

        var classNameOfParent = $(this).parent().attr('class');

        var classNameToBePassedByUrl = "home";

        if(classNameOfParent.contains("group"))
            classNameToBePassedByUrl = "group";
        else if(classNameOfParent.contains("people"))
            classNameToBePassedByUrl = "people";

        location.href = $(this).attr('href') + "#activeClass=" + classNameToBePassedByUrl;
    });
});
Milad Rashidi
  • 1,296
  • 4
  • 22
  • 40
0

I don't think you should be changing the "active" class just when the li links are clicked. Think that when you redirect your users to a specific page from another, the li links "OnClick" event won't be fired at all, hence, the active menu link won't be displayed appropriately. Now, what I usually do to solve this issue (don't know if it's the most elegant solution, but it works) is to place a tag at the top of each html content template (I'm assuming you're using templates for the Header, Footer and Content here), I give it a descriptive ID, like "page-name" or "section", and add a data attribute to it with the name of the menu link that this page "belongs" to:

<div id="page-name" data-page="home-page">

Then with JQuery you can ask for the div's data like this:

var current_page = $("#page-name").data("page");

And simply alter the menu links class depending on what page the user is currently in:

// remove the "active" class from ALL the links first
$(".menu li a").removeClass("active");

if (current_page === "home-page") {
    // add the "active" class just to the link you want
    $("#home-page-link").addClass("active")
}

Of course, you would do that with a switch and you would have to load the js file on ALL pages (that's why the use of the Header template is so important, since you would just need to include it once). Also, in the html "data-page" attribute, the "page" part can be anything, just remember to call it appropriately later. Hope I helped.

Alex_89
  • 371
  • 5
  • 15
  • But we don't know what does the test.php and test2.php consist of, and whether if they are just HTML pages or do they run a script and redirect back. –  Dec 12 '17 at 16:39
  • test.php and test2.php does not contain any header or script tags to redirect the user back a previous page. – Andre Reid Dec 12 '17 at 16:44
  • @Alex_89 for you solution, #home-page-link is the actual link to the active page. For example, #test.php – Andre Reid Dec 12 '17 at 17:36
  • No, $("#home-page-link") selector in this case references the actual menu link (i.e.: a specific li tag or button in your menu). The one you want to highlight, for example. – Alex_89 Dec 13 '17 at 13:54
0

To dynamically add a class, on page load, to the navigation item of the current page, consider:

  1. Checking the current page url:
    $(location).attr('href') OR $(location).attr('pathname')
  2. Looping through anchor elements (a) of the navigation menu to determine if any of the href attribute values match the current page url with a conditional check using the .indexOf() method:
    if(anchorEl.indexOf(currentPageUrl) >= 0)
  3. If any do, add the required class, using the .addClass() method: $(this).addClass('current');

Code Snippet Demonstration:

Note: Intended for the sake of demonstration
The code snippet embedded below uses specific urls to provide a working example and to demonstrate the intended functionality. Adjust accordingly to apply to a given production environment.

$(document).ready(function () {
    var currentPageUrl = $(location).attr('href'), // store current page url in variable
        anchorEl;
    
    $('.menu a').each(function(){
    
      anchorEl = $(this).attr('href'); // store href atribute of current anchor element in iteration
      console.log('anchor link url:',anchorEl);
      console.log('current url of window:',currentPageUrl);
    
      if(anchorEl.indexOf(currentPageUrl) >= 0) { // if anchor element contains 
        $(this).addClass('current');
        console.log('class "current" was added.');
      }
    });
});

/*

Note:
$(location).attr('href') = full absolute path (https://stacksnippets.net/js)
$(location).attr('pathname') = relative path (/js)

*/
.current {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="menu">
  <ul class="list">
    <li>
      <a href="https://stacksnippets.net/foobar1">
          <span>foobar #1</span>
      </a>
    </li>
    <li>
      <a href="https://stacksnippets.net/foobar2">
          <span>foobar #2</span>
      </a>
    </li>
    <li>
      <a href="https://stacksnippets.net/js">
          <span>This should be the <em>current</em> url</span>
      </a>
    </li>
  </ul>
</div>
UncaughtTypeError
  • 8,226
  • 4
  • 23
  • 38
0

i had the same problem after a lot of searching i could find this solution in this link i hope it could help you. Although you should remove class active and add class active to clicked navbar item ,you should use location.href to add active class when the new page reload.

https://santosh-shah.com/add-class-active-page-refresh-jquery/

  • 1
    Please include your own answer, and conclude it. Don't copy and paste some reference, reference can be added for more details but not as an answer. – AlokeT Feb 20 '19 at 11:45