Mavigator - Marking Your Navigators with Ease
Marking our website's navigators can sometimes be a non-trivial task. Such a simple thing to do can sometimes take a while to implement robustly. But what if we could make this task a no-brainer?
The Issue 🤔
If your backend language of choice is PHP, you may have written the following code over and over for pretty much every project:
<a href="/" class="<?php echo $_SERVER['REQUEST_URI'] == '/' ? 'active' : '' ?>">Home</a>
<a href="/about" class="<?php echo $_SERVER['REQUEST_URI'] == '/about' ? 'active' : '' ?>">About</a>
<!-- ... -->
You may have written a function and made it slightly less verbose:
function activeClass($uri, $activeClass = 'active')
{
echo $_SERVER['REQUEST_URI'] == $uri ? $activeClass : '';
}
Then, you may use it like so:
<a href="/" class="<?php activeClass('/') ?>">Home</a>
<a href="/about" class="<?php activeClass('/about') ?>">About</a>
However, our code will break if the current route has a query parameter as the $_SERVER['REQUEST_URI']
will also match that query parameter, resulting in the following check:
echo '/about?name=john' == '/about' ? active : '';
Sure, we can easily fix it by using PHP's parse_url() method, but we are still required to repeat this code for every single link on our page that we want to mark.
Offloading the task 🏋️♂️
I would like to propose a different approach. Why won't we offload the task of marking our navigators to the client-side?
Let's take a quick look at how we might go about implementing that.
Given we have the following navigator markup which we want to mark:
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
We can use Javascript to scan the links in our <nav>
element and mark the correct link:
const links = document.querySelectorAll('nav a');
links.forEach(link => link.pathname === window.location.pathname && link.classList.add('active'));
Believe it or not, that's the essence of it. We can, of course, keep working on that script and make it more sophisticated, taking into account cases where we want to apply the active
class to the parent of the link, or cases where the page URI is a "resource" link and we need to mark some other link on the page; for example, if the page URI is example.com/forum/some-thread-slug
and we want to mark a link with the pathname of /forum
.
Just so you won't need to write this logic yourself, I've written a small package to do just that. I call it Mavigator.
Mavigator Got your Back 👀
Mavigator is a lightweight, intelligent script that will mark your navigators.
Mavigator looks for any anchor tag (<a>
) inside a given selector (which incidentally defaults to html
), scans each node and figures out whether it needs to be marked or not.
If needed, you can scope the <a>
tag scanning to a specific element type such as <nav>
, a class name or an ID.
The Mavigator.mark()
method's blueprint is:
Mavigator.mark(selector, options);
Where selector
is a string compatible with document.querySelectorAll()
. The default selector is html
.
If you don't wish to override the selector but supply the options object, you can also pass the options as the first argument and the selector will default to html:
// This will set the `selector` to "html" and use the given options.
Mavigator.mark(options);
The options
are as follow:
Property | Default value | Description |
---|---|---|
className | "active" | The class which will be added to the element once found. |
uri | window.location.pathname | The uri Mavigator will try to find on anchor tags. The default value is okay in most cases. When you want to mark a link that its uri is '/discuss' and the uri of the page is something like '/discuss/general/how-we-do-x' we can use this option to tell Mavigator to look for the '/discuss' uri. |
classToParent | false | Whether to add the className to the anchor tag or its parent. |
markTreeDepth | 0 | Tells Mavigator whether it should "expand" the URI to match. The possible values are:
|
warn | false | Whether to warn in the console if no link to mark was found. |
You can read more about Mavigator on Github.
I hope you find this package useful. Happy coding!