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
Related
I want to check if the current url contains the parent url to add an "active" class to the parent list item link.
jQuery(function($) {
var path = window.location.pathname;
$('ul a').each(function() {
if (this.pathname.indexOf( path )) {
$(this).addClass('active');
}
});
});
My html looks like this:
<ul>
<li><a class="list-link">Posts</a></li>
<li><a class="list-link">Blog</a></li>
<li><a class="list-link">Contact</a></li>
</ul>
When going to domain.com/contact/email I want to keep the list item to keep the "active" class.
If I understand your question correctly, you're wanting to add the active class to anchor elements in your ul list, if the anchor's text exists in the current browser path.
That can be achieved via the following (see documentation in snippet for details):
jQuery(function($) {
//var path = window.location.pathname;
var path = 'domain.com/contact/email';
// Convert path to lower case for easier matching
path = path.toLowerCase();
$('ul a').each(function() {
// Extract link label via text() method. Convert
// label to lower case for easier matching
var label = $(this).text().toLowerCase();
// Use indexOf() to check for label existing in
// path
if( path.indexOf(label) !== -1 ) {
// Add active class if match found
$(this).addClass('active');
}
});
});
.active {
background:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<ul>
<li><a class="list-link">Posts</a></li>
<li><a class="list-link">Blog</a></li>
<li><a class="list-link">Contact</a></li>
</ul>
UPDATE
I found what I was looking for using this jQuery code:
jQuery(function($) {
var path = window.location.pathname.split( '/' )[2];
$('ul a').each(function() {
if (this.href.indexOf( path ) != -1) {
$(this).addClass('active');
}
});
});
Anchors don't have a pathname property. Change the line to check the text contained within the anchor:
if (this.textContent.indexOf( path )) {
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.
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).
$('#sidebar ul li ul li').click(function () {
var ids = $(this).attr('id');
$('#ids').addClass('active');
$('#ids').parent('ul').parent('li').addClass('has-sub active');
alert(ids); // Will alert the id if the element has one
});
I didn't understand why this is not working. alert gives me the id of the li element but the 2 lines before it don't work I mean these 2:
$('#ids').addClass('active');
$('#ids').parent('ul').parent('li').addClass('has-sub active');
Where is the problem? Am I missing something?
You need to concatenate your variable like:
$('#' + ids).
$('#ids') is looking for an element with the ID of ids. And as Blender noted in the comments, why are you doing it this way? The element you're clicking on could be referred to as simply $(this) or this. To me it might make more sense to do:
$('#sidebar ul li ul li').click(function () {
$(this).addClass('active').parent('ul').parent('li').addClass('has-sub active');
});
And you might also be able to replace .parent('ul').parent('li') with .closest('li'), but I'd need to see the HTML structure to be sure.
You are taking the id of the current element to concatenate together a selector. Instead, you can use the this keyword within the handler and use it as a reference to the clicked element. Try this:
$('#sidebar ul li ul li').click(function () {
$(this).addClass('active').closest('li').addClass('has-sub active');
});
ids is a variable which holds the id of clicked element. and in your code:
$('#ids').addClass('active');
$('#ids').parent('ul').parent('li').addClass('has-sub active');
You use ids as a string. This is not correct way. You should replace $('#ids') with $('#' + ids).
Try this:
$('#' + ids).addClass('active');
$('#' + ids).parent('ul').parent('li').addClass('has-sub active');
Did you mean to apply the new classes to the ids in the variable ids? If so you are currently applying those to elements that have the id of 'ids'. You should use the following selector: $('#'+ids).
#IshanJain #RoryMcCrossan #j08691 #EliantenHolder thank you for your response. Jquery doesnt help to solve this problem but this helper worked.
public static class HtmlHelperExtensions
{
public static string ActivePage(this HtmlHelper htmlHelper,string controller, string action)
{
string _classValue="";
string _currentController = htmlHelper.ViewContext.Controller.ValueProvider.GetValue("controller").RawValue.ToString();
string _currentAction = htmlHelper.ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString();
if (_currentController == controller && _currentAction == action)
{
_classValue = "active";
}
else if (_currentController == controller && action.Equals(""))
{
_classValue = "has-sub active";
}
else
{
if (action.Equals(""))
{
_classValue = "has-sub";
}
}
return _classValue;
}
}
and this is from my layout page
<li class="#Html.ActivePage("Order","")">
<a href="javascript:;" class="">
<span class="icon-box"> <i class="icon-dashboard"></i></span> Sipariş Açma
<span class="arrow"></span>
</a>
<ul class="sub">
<li class="#Html.ActivePage("Order","Index")"><a class="" href="#Url.Action("Index","Order")">Sipariş</a></li>
<li class="#Html.ActivePage("Order","orderProduct")"><a class="" href="#Url.Action("orderProduct","Order")">Ürün Sipariş</a></li>
<li class="#Html.ActivePage("Order","orderCloth")"><a class="" href="#Url.Action("orderCloth","Order")">Kumaş Sipariş</a></li>
<li class="#Html.ActivePage("Order","orderAccessory")"><a class="" href="#Url.Action("orderAccessory","Order")">Aksesuar Sipariş</a></li>
</ul>
</li>
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");
}
});