active class on menu and parent item - javascript

i have this HTML code for my menu:
<nav id="main-navigation" class="navigation-simple">
<ul>
<li>Home</li>
<li><a class="active-nav" href="">About Us</a>
<ul>
<li><a class="active-nav" href="about">About</a></li>
<li>Testimonials</li>
<li>Meet The Team</li>
</ul>
</li>
</nav>
i have added in the active-nav class but how can i automatically set the active class on parent and child items when the current URL is the href value of the link?

you need java script for this, jQuery is great for beginners!
It could be done like this:
var url = window.location.href;
$( "nav li a" ).each(function(index) {
if (url.indexOf($(this).attr('href')) >= 0){
$(this).addClass('active-nav');
}
});
line by line -
get the current page url
for each link in the navigation...
check if its href is in the current url
if it is, add the class 'active-nav'
close if statement
close for loop

You can use the .filter() method to find the appropriate link and add the required class:
$('#main-navigation li > a').removeClass('active-nav')
.filter(function() {
return location.href.indexOf(this.href) > -1;
})
.addClass('active-nav') //add class to matched element(s)
//add class to parent(s) of matched, if any
.each(function() {
$($(this).parents('a'), '#main-navigation').addClass('active-nav');
});
Also remember to close your first ul.

Something like:
$(function() {
$('#main-navigation a').each(function() {
if(this.href.indexOf(window.location.pathname) === 0) {
$(this).addClass('active-nav');
} else {
// case when something was set to active by the server
$(this).removeClass('active-nav');
}
});
});
will do the job.
Make sure you make the if condition safe to your sites deeplinking implementation (e.g. GET params, anchors or multiple domains with same pathname are possible within your navigation).

Related

Add active class to parent nav when on child pages

I need to highlight the parent nav item when a user is within a child page based on the URL.
User is currently on the page foo1-child and the parent is foo1 so I need to add the active class to Foo 1: http://foo.com/foo1/foo1-child.html
NAV:
<ul class="main-nav">
<li>Foo 1</li>
<li>Foo 5</li>
</ul>
I have no issue adding an active class to links within the nav as I just compare every the href in the .nav li a vs the URL but how can I check the URL for a matching anchor link name in the URL or something similar?
Current JS
$('.main-nav li > a').each(function () {
var $this = $(this);
if ($this.attr('href').indexOf(location.pathname) !== -1) {
$this.addClass('active');
}
});
If you cut off the ".html" from the end of both of them and you search for the a's href (which should be shorter) in the location, it should work.
$('.main-nav li > a').each(function () {
var $this = $(this);
var loc = location.
if (location.pathname.replace(/\/[^\/]*\.html$/, '').startsWith($this.attr('href').replace(/\.html$/, ''))) {
$this.parent().addClass('active');
}
});
You can see it in "action" here: https://jsfiddle.net/c8u2f91v/ Note it uses a fake location_pathname instead of location.pathname, because jsfiddle doesn't have the necessary prefixes in the path, but it shows that it should work.

dynamically apply active class to nav li

I have included a header to my files as in include. In the header is the nav bar.
How do I, using jQuery, apply class="active" to the relevant li.
The only way I could think of doing it is to set a variable on the actual pages, apply an id that is equal to that variable of the relevant page and if function so if they match apply a class to the li.
However, I thought there must be a simpler way of achieving this.
<ul class="nav nav-pills right" id="div">
<li id="home" class="active">
Home
</li>
<li id="search">
Search
</li>
<li id="contact">
Contact
</li>
</ul>
An easy way to do this would be to have a script per page:
$('#home').addClass('active'); // for home page
You could try and match the href to the current url:
var path = window.location.pathname.substring(1);
$('.nav>li>a[href="' + path + '"]').parent().addClass('active');
More compact way:
$(function(){
var sPath = window.location.pathname;
var sPage = sPath.substring(sPath.lastIndexOf('/') + 1);
$('a[href="'+ sPage +'"]').parent().addClass('active');
});
As soon as the page loads it will run this code:
$(document).ready(function(){
$('li').removeClass('active');
$('li a').each(function() {
$found = $.contains($(this).prop("href"),location.pathname);
if ($found) {
$(this).closest('li').addClass('active');
break;
}
});
});
OR
You can also do this using regex :
$(document).ready(function(){
$('li').removeClass('active');
var regex = /[a-z]+.php/g;
var input = location.pathname;
if(regex.test(input)) {
var matches = input.match(regex);
$('a[href="'+matches[0]+'"]').closest('li').addClass('active');
}
});
You might need to have the similar id name to that of php file.
Check the demo here : Demo
You can do this:
//remove the active class from all items, if there is any
$('.nav>li').removeClass('active');
//finally, add the active class to the current item
$('a[href='+ location.pathname.substring(1) +']').parent().addClass('active');
You could use javascript to find the current list item based on the url, by adding the class to the right list item after the DOM has been loaded (e.g. string manipulation of window.location together with JQuery selectors and addClass())
I found a routine to set active (current) class on my shared menu, but I need to modify it to set the parent link only, and not the 'closest' link. It works great on menu items with no sub menus, but when a sub menu item is clicked, there is not indication on the main menu after page load. (the code I need to modify is below)
(function( $ ) {
$.fn.activeNavigation = function(selector) {
var pathname = window.location.pathname
var extension_position;
var href;
var hrefs = []
$(selector).find("a").each(function(){
// Remove href file extension
extension_position = $(this).attr("href").lastIndexOf('.');
href = (extension_position >= 0) ? $(this).attr("href").substr(0, extension_position) :
$(this).attr("href");
if (pathname.indexOf(href) > -1) {
hrefs.push($(this));
}
})
if (hrefs.length) {
hrefs.sort(function(a,b){
return b.attr("href").length - a.attr("href").length
})
hrefs[0].closest('li').addClass("current")
}
}; })(jQuery);
If someone still checks on google how to do it here is my solution
var path = window.location.href; // full url
$('a[href="'+ path +'"]').parent().addClass('active'); // find by selector url
HTML
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="http://example.com/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="http://example.com/history"> History</a>
</li>
</ul>

How can i change the css class based on keywords in url with jquery

I have the navigation bar as below
<ul>
<li class="selected"><a href=">My Profile</a></li>
<li>xxxx</li>
<li>mybook</li>
<li>Photos <span>4</span></li>
<li>Profile List</li>
</ul>
I want that if the url is www.abc.com/user/profile then profile tab class should have class selected attached
If photos then photo tab.
If we can have partial match that will be good but i am not sure if thats possible
like in url i have /user/book and myBook gets selected
Some elegant variant:
<ul class="menu">
<li><a class="profile" href="/user/profile">My Profile</a></li>
<li><a class="book" href="/user/book">My Book</a></li>
</ul>
$(document).ready(function () {
var page = document.location.href.split('/').slice(-1)[0];
$('.menu .' + page).addClass('selected');
});
You can grab the part you want with regex:
var userPage = /user\/(.+)/.exec(location.href)[1];
That will give you the part after user/. Then you could use a switch statement:
switch (userPage) {
case 'profile':
...
break;
case 'book':
...
break;
}
You would want to switch off of location.pathname. Granted that you give that <ul> a class of nav:
$(function () {
if (location.pathname.search("/user/profile") != -1) {
// page is /user/profile
$("#nav li").eq(0).addClass("selected");
} else if (location.pathname.search("/user/photos") != -1) {
// page is some/thing
$("#nav li").eq(3).addClass("selected");
}
... etc
});
Things to notice
We use $(function () {...}); as opposed to $(document).ready(function() {...});. It is less typing and more efficient
We use String.search(), which returns the index at which the string "/user/profile" appears. If the string is not found, String.search() will return -1, so if it != -1, it exists.
We also use jQuery.eq( index ) this treats elements selected by a jQuery selector as an array and returns the element of the specified index.
References
Check out jQuery's .eq here, and JavaScript's String.search here

Toggle css class using Jquery

I have a standard ul-based CSS navigation menu. I'm trying to use Jquery to toggle the active menu css class name. However, I'm encountering two issues:
The window.location.href never equals any of my anchor hrefs. I switched to pathname, but they still do not match each other. Even though in the debugger they appear to.
I cannot seem to get the li from it's anchor.prev. I need to change the class name on the li.
Here's the html:
<div id="left-content">
<ul>
<li class="separator">Main
<ul>
<li class="active link">Main 1</li>
<li class="link">Main 2</li>
<li class="link">Main 3</li>
</ul>
</li>
<li class="separator">Tools
<ul>
<li class="link">Tools 1</li>
</ul>
</li>
</ul>
</div>
When an anchor is clicked, it's corresponding li should have "active link" as the class name. And all other li's should be reset to just "link" as the class name.
Here's the Jquery javascript:
function toggle_active_menu() {
$('#left-content a').each(function() {
/*var isActive = $(this).attr('href') == window.location.href;*/
var active = this.pathname == window.location.pathname;
var prev = this.prev();
alert("active: " + active + "\nthis.pathname: " + this.pathname + "\nwindow.location.pathname: " + window.location.pathname + "\nprev: " + prev);
prev.toggleClass('active', active);
});
}
I put the alert in there to help debug. As I mentioned, the clicked anchor's href (or pathname) never matched the window's location href (or pathname). And prev is always undefined instead of being the li of the anchor.
Eventual Answer
After testing the various answers, I fould that I had to remove the onclick calls and call the toggle_active_menu function in the document ready function instead. The window location was not being updated before onclick was being called. Also, I did not use toggleClass so that I could preserve the order of the class names.
function toggle_active_menu() {
$('#left-content ul li ul li a').each(function() {
var pathname = window.location.pathname == '/' ? '/main1' : window.location.pathname;
var active = pathname.indexOf(this.pathname) != -1;
if (active) {
$(this).parent().attr('class', 'active link');
} else {
$(this).parent().attr('class', 'link');
}
});
}
To get the li which is the parent of a element use parent method and toggleClass take only the calss to toggle. To compare the href of the anchor with window.location.href you can use indexOf method.
function toggle_active_menu() {
$('#left-content a').each(function() {
var isActive = (window.location.href.toLowerCase().indexOf($(this).attr('href')) != -1);
$(this).parent().toggleClass('active');
alert("active: " + isActive);
});
}
Simplified version for you.
$('.link').click(function(){
$('.link').removeClass('active');
$(this).addClass('active');
})
toggleClass only takes one paramater it should be
prev.toggleClass('active');
To fix getting a handle on the correct LI to toggle the class, try
var prev = $(this).parent();
For the pathname, try using $(this).attr("href") and matching it against window.location.href, or checking if it's contained within window.location.href

How to find the 2nd closest ancestor in jQuery?

My DOM looks something like this:
<li>
<li><a class="editEntity>Edit</a></li>
<li><a class="deleteEntity>Delete</a></li>
</li>
When the used clicks on 'Edit', I want to change the outer <li> to <li class="selected>.
I tried something like this, but this is not working:
$('li a.editEntity').live('click', function() {
$(this).closest('li').closest('li').addClass('selected');
});
Any help is appreciated.
Go up a parent:
$(this).closest('li').parent().closest('li').addClass('selected');
It wasn't working because closest starts with the current element, and so if you call it on something that matches the selector, you get back the same thing you started with.
Live example
Or you can use parents with the :eq selector:
$(this).parents("li:eq(1)").toggleClass("selected");
Note that :eq uses 0-based indexes, so :eq(1) is the second parent li.
Live example
Your quoted HTML is invalid, though (an li can't directly contain an li); I assume you meant:
<li>
<ul>
<li><a class="editEntity>Edit</a></li>
<li><a class="deleteEntity>Delete</a></li>
</ul>
</li>
...or similar.
you can use
$('li a.editEntity').live('click', function() {
$(this).parents('li').addClass('selected');
});
following my previous comment.. here's the example promised... :)
$('li').each(function(index) {
alert(index + ': ' + $(this).text());
});
Stop at the second index
Further info can be found here
http://api.jquery.com/each/
I'm using this code to add active class depending on the page. This is working 100% for multi level sub-menus of AdminLTE 3, just put this code in the footer section of your page.
var url = window.location;
const allLinks = document.querySelectorAll('.nav-item a');
const currentLink = [...allLinks].filter(e => {
return e.href == url;
});
currentLink[0].classList.add("active");
currentLink[0].closest(".nav-treeview").style.display = "block ";
currentLink[0].closest("ul.nav-treeview").closest('li').classList.add('menu-open');
$('.menu-open').find('a').each(function() {
if (!$(this).parents().hasClass('active')) {
$(this).parents().addClass("active");
$(this).addClass("active");
}
});

Categories