Barba: Reload Navigation Menu to update Current highlighted menu

Created on 13 Jul 2016  Â·  10Comments  Â·  Source: barbajs/barba

Able to reload the navigation menu <ul class="main-navigation-menu"> to load the updated and highlighted navigation menu.

     <ul class="main-navigation-menu">
        <li class="current"><a href="index.php">Home</a></li>
        <li><a href="index.php">Home</a></li>
     </ul>
question

Most helpful comment

@Jonathlee
This should do the job:

<header>

    <nav class="navigation">
      <ul>
        <li><a href="index.html" class="navigation__link is-active">Home</a></li>
        <li><a href="about/index.html" class="navigation__link">About</a></li>
        <li><a href="about/team/index.html" class="navigation__link">Team</a></li>
      </ul>
    </nav>

  </header>

  <div id="barba-wrapper">

    <div class="barba-container">
      …
    </div>

  </div>
.navigation .is-active {
  color: red;
}
// Barba.js
Barba.Pjax.start();
Barba.Prefetch.init();

Barba.Dispatcher.on('newPageReady', function(currentStatus) {
  const link = currentStatus.url.split(window.location.origin)[1].substring(1); // get path of current page

  const navigation             = document.querySelector('.navigation');
  const navigationLinks        = navigation.querySelectorAll('.navigation__link');
  const navigationLinkIsActive = navigation.querySelector(`[href="${link}"]`);

  Array.prototype.forEach.call(navigationLinks, (navigationLink) => navigationLink.classList.remove('is-active')); // remove CSS class 'is-active' from all .navigation__links

  navigationLinkIsActive.classList.add('is-active'); // add CSS class to current .navigation__link

});

All 10 comments

Hi @Jonathlee .

In order to update the menu current items you have two choices:

  1. Put the menu inside the .barba-container, so it will changed at each page "change"
  2. Manually update the active class via JS (you can use Events)

I invite you to read this article I wrote in order to better understand how barba.js works.

Let me know if you have any other question :)
Feel free to close the issue if you solved the problem.

@luruke thank you very much for the answer.

@Jonathlee
This should do the job:

<header>

    <nav class="navigation">
      <ul>
        <li><a href="index.html" class="navigation__link is-active">Home</a></li>
        <li><a href="about/index.html" class="navigation__link">About</a></li>
        <li><a href="about/team/index.html" class="navigation__link">Team</a></li>
      </ul>
    </nav>

  </header>

  <div id="barba-wrapper">

    <div class="barba-container">
      …
    </div>

  </div>
.navigation .is-active {
  color: red;
}
// Barba.js
Barba.Pjax.start();
Barba.Prefetch.init();

Barba.Dispatcher.on('newPageReady', function(currentStatus) {
  const link = currentStatus.url.split(window.location.origin)[1].substring(1); // get path of current page

  const navigation             = document.querySelector('.navigation');
  const navigationLinks        = navigation.querySelectorAll('.navigation__link');
  const navigationLinkIsActive = navigation.querySelector(`[href="${link}"]`);

  Array.prototype.forEach.call(navigationLinks, (navigationLink) => navigationLink.classList.remove('is-active')); // remove CSS class 'is-active' from all .navigation__links

  navigationLinkIsActive.classList.add('is-active'); // add CSS class to current .navigation__link

});

@marcobiedermann (a bit old but thought this might help someone)
In my case navigationLinkIsActive was always returning a null object. Changing '[href="${link}"]'); to ("a[href='" + link + "']") seems to work, although the why is beyond my js level :)

Thanks again!

@psamhaber In the example @marcobiedermann was using the ES6 template literals and not the simple single quote. That's why ;)

Anyway now barba.js newPageReady has a fourth argument which contains the raw HTML of the new page, maybe it's easier to use it in order to change the active of the nav bar.

Cheers

I see! Thanks for taking the time to explain, much appreciated!

Re: using newPageRawHTML instead: I reckon the performance of this vs the above code would be similar for not overly complex pages?

Cheers

Got it working like this. First add a way to recognize elements that need to be updated, like data-barba-update. Then add this code:

Barba.Dispatcher.on('newPageReady', function(newStatus, oldStatus, container, html) {
  const navs = $(html).find('[data-barba-update]') // New ones
  $('[data-barba-update]').each((i,el) => $(el).html($(navs[i]).html())) // Replace each old ones
})

Expanding on @nicooprat 's example, you can do something like this, which will update only the classes, rather than all of the markup..

    const navs = $(html).find('[data-barba-update]');

    $('[data-barba-update]').each(function(index) {
        const newClasses = $(navs[index]).get(0).classList.value;
        $(this).attr('class', newClasses);
    });

@jacobimpson that's pretty nice! Any chance you have a vanilla js example?

Edit:
Ah. Struggled with parsing. Duh...

Here's where I ended up;

const parser = new DOMParser();
const content = parser.parseFromString(html, "text/html");
const navs = content.querySelectorAll('.navigation__link');
document.querySelectorAll('.navigation__link').forEach(function(el, index) {
    const classes = navs[index].classList.value;
    el.setAttribute('class', classes);
});

Maybe it's a little bit out of the topic and i apologize in advance.
I was also playing with that and did on my way

          var url = $(location).attr('href').replace(/\/+$/,''),
              parts = url.split("/"),
              last_part = parts[parts.length-1];
                $("nav ul a").each(function(idx, li) {
                  if($(this).attr('href').includes(last_part)) {
                    $(this).removeAttr('href');
                  }
                });

My problem is that when i click 2nd time on - #hamIcon - i got err - Uncaught TypeError: Cannot read property 'includes' of undefined.
Seems like var last_part is undefined

Menu is out of .barba-container

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mellis84 picture Mellis84  Â·  3Comments

lasagner picture lasagner  Â·  3Comments

iamtompickering picture iamtompickering  Â·  3Comments

shanewmurphy picture shanewmurphy  Â·  3Comments

3oax picture 3oax  Â·  4Comments