0

I have created 2 menus called "Habit Setting" and "Team Setting" enter image description here

But after clicking on second menu the page is reloading and the menu background is not going to second menu. There is always showing menu background of the first menu. Would like to have a better solution for that.

Here is my code -

<?php
  defined('ABSPATH') or exit;

  // TODO: Refactor tabs
?>

<div id="myDIV">
<nav class="bp-navs bp-subnavs no-ajax user-subnav" id="subnav" role="navigation" aria-label="Sub Menu">
<ul class="subnav">

    <li class="bp-personal-sub-tab current selected">
        <a href="<?php echo site_url('settings/habit-settings/'); ?>" class="btn active"> Habit Setting </a>
    </li>
    
    <li class="bp-personal-sub-tab current">
        <a href="<?php echo site_url('settings/team-settings/'); ?>" class="btn"> Team Setting </a>
    </li>


</ul>
</nav>
</div><!-- .item-list-tabs#subnav -->


<!--  Add active class to the current list -->

<style>

.btn {
  outline: none !important;
  cursor: pointer !important;
}

.active, .btn:hover {
  background-color: red !important;
  color: red;
}

</style>

<script>
var header = document.getElementById("myDIV");
var btns = header.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
  btns[i].addEventListener("click", function() {
  var current = document.getElementsByClassName("active");
  current[0].className = current[0].className.replace(" active", "");
  this.className += " active";
  });
}
</script>

I was trying to show active menu color through JS but my code doesn't work.

  • The state of the page in the browser is not kept between reloads (as also the word may suggest). Question remains why would you expect it to be otherwise? – hakre Nov 20 '22 at 14:27
  • 1
    make your `class="btn active"` dynamic, like check if the page is set to the url, then active should be true for it. – Ibrahim Hammed Nov 20 '22 at 14:51

2 Answers2

0

Why

This is because javascript does not save element state between pages.


Solution

I recommend using the same page to "include" another page.

First, create a page for routing, add the code:

<div id="myDIV">
    <nav class="bp-navs bp-subnavs no-ajax user-subnav" id="subnav" role="navigation" aria-label="Sub Menu">
        <ul class="subnav">

            <li class="bp-personal-sub-tab current selected">
                <a href="?page=habit-settings" class="btn" id="habit-settings"> Habit Setting </a>
            </li>

            <li class="bp-personal-sub-tab current">
                <a href="?page=team-settings" class="btn" id="team-settings"> Team Setting </a>
            </li>
        </ul>
    </nav>
</div><!-- .item-list-tabs#subnav -->

The difference from what you wrote is to change the url to "?page=habit-settings" and "?page=team-settings".

So when you click the link, you will send the parameter "page" to the current page through the get method.

Then get the parameter, add the following code:

<?php
$pageTable = [
    'habit-settings' => 'settings/habit-settings.php',
    'team-settings' => 'settings/team-settings.php',
];
$pageTable['default'] = $pageTable['habit-settings'];

$currentPage = isset($_GET['page']) ? $_GET['page'] : 'habit-settings';

if(isset($pageTable[$currentPage])){
    include($pageTable[$currentPage]);
}else{ include($pageTable['default']); }
?>

$currentPage = isset($_GET['page']) ? $_GET['page'] : 'default'; means that if got the parameter "page", then set $currentPage to it, otherwise set to the "default".

The $pageTable means that the file path corresponding to the page name, for example, the page name "habit-settings" corresponds to the file "settings/habit-settings.php". And set the default page to it "$pageTable['default'] = $pageTable['habit-settings']".

Check if page name is not in the page table: !isset($pageTable[$currentPage]), if not, change the $currentPage to "default".

Then include the page: include($pageTable[$currentPage])

Now you can change page through click the links.

You want to highlight the link corresponding to the current page, so add the js code:

<script>
    var header = document.getElementById("myDIV");
    var btns = header.getElementsByClassName("btn");
    var currentPage = "<?php echo isset($_GET['page']) ? htmlentities($_GET['page']) : 'habit-settings'; ?>";

    for (var i = 0; i < btns.length; i++) {
        if (btns[i].id !== currentPage) continue;
        btns[i].className += " active";
    }
</script>

Create the variable "currentPage" to save the PHP variable $currentPage. And find the btn element which id same as current page name, if not equal, "continue" the for loop, else add its class name "active".


Done

enter image description here


Full code


<div id="myDIV">
    <nav class="bp-navs bp-subnavs no-ajax user-subnav" id="subnav" role="navigation" aria-label="Sub Menu">
        <ul class="subnav">

            <li class="bp-personal-sub-tab current selected">
                <a href="?page=habit-settings" class="btn" id="habit-settings"> Habit Setting </a>
            </li>
            
            <li class="bp-personal-sub-tab current">
                <a href="?page=team-settings" class="btn" id="team-settings"> Team Setting </a>
            </li>
        </ul>
    </nav>
</div><!-- .item-list-tabs#subnav -->

<?php
$pageTable = [
    'habit-settings' => 'settings/habit-settings.php',
    'team-settings' => 'settings/team-settings.php',
];
$pageTable['default'] = $pageTable['habit-settings'];

$currentPage = isset($_GET['page']) ? $_GET['page'] : 'default';

if(isset($pageTable[$currentPage])){
    include($pageTable[$currentPage]);
}else{ include($pageTable['default']); }
?>


<!--  Add active class to the current list -->
<style>
    .btn {
        outline: none !important;
        cursor: pointer !important;
    }

    .active, .btn:hover {
        background-color: red !important;
    }
</style>

<script>
    var header = document.getElementById("myDIV");
    var btns = header.getElementsByClassName("btn");
    var currentPage = "<?php echo isset($_GET['page']) ? htmlentities($_GET['page']) : 'habit-settings'; ?>";

    for (var i = 0; i < btns.length; i++) {
        if (btns[i].id !== currentPage) continue;
        btns[i].className += " active";
    }
</script>
Alpaca0x0
  • 45
  • 6
  • 1
    It is a nice and well-written answer, though overcomplicated. You introduce a new GET parameter, without it the menu highlighting would not work anymore. And you use JS and PHP currently for a simple assignment of a class. Instead, you could either with JS or PHP check the current URL and check it against the meni items href attribute. --- PHP would be preferable as the HTML code would be delivered already with the class and there would be no change in the markup, after the site arrived at the user. – Uwe Nov 20 '22 at 19:07
  • @Uwe Yes, it relies on the 'GET' method, and it's not a good solution enough. If don't want to use 'GET' method, maybe can try to create a const `PAGE` in `habit-settings` and `team-settings` pages, and set the const value to "`habit-settings`" and "`team-settings`", then include the menu page in these two pages. In menu page, it can know the current page through check the value of const 'PAGE', and highlight the links. – Alpaca0x0 Nov 21 '22 at 05:27
  • I am not the questioner. Your answer to the problem is very well structured and I saw the effort you put in and wanted to give you some feedback. – Uwe Nov 21 '22 at 09:29
  • @Uwe Haha, Thanks for your encouragement and discussion with me :D – Alpaca0x0 Nov 21 '22 at 13:33
0

You could check the path of your href attributes in your navigation against the requested URL with if ($path === 'YOUR-HREF -STRING') { echo 'active';} ?>"

$path you get with $path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); --> see this answer

Additionally info: the $path variable always starts with a /.

<?php $path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH); ?>
<ul class="subnav">
    <li class="bp-personal-sub-tab current selected">
        <a href="<?php echo site_url('settings/habit-settings/'); ?>" class="btn <?php if ($path === '/settings/habit-settings/') { echo 'active';} ?>"> Habit Setting </a>
    </li>
    
    <li class="bp-personal-sub-tab current">
        <a href="<?php echo site_url('settings/team-settings/'); ?>" class="btn <?php if ($path === '/settings/team-settings/') { echo 'active';} ?>"> Team Setting </a>
    </li>

</ul>
Uwe
  • 385
  • 1
  • 5
  • 14