Reputation: 2354
I have a ul element in my html..
<ul class="sidebar-menu"> /<ul>
which can have <li>
elements of two kinds..
a) simple..
<li>
<a href="/Campaign/CreateCampaignUrl">
<i class="fa fa-th"></i> <span>Campaign Url</span>
<small class="label pull-right bg-green">new</small>
</a>
</li>
b) complex..
<li class="treeview">
<a href="#">
<i class="fa fa-files-o"></i>
<span>Classify Events</span>
<span class="label label-primary pull-right">4</span>
</a>
<ul class="treeview-menu">
<li><a href="/ClassificationUI/ClassifyStandardEvent"><i class="fa fa-circle-o"></i> Standard Events</a></li>
<li><a href="/Campaign/ClassifyCampaignProperties"><i class="fa fa-circle-o"></i> Campaign Properties</a></li>
</ul>
</li>
I wish to add class attribute with value 'active' to a specific <li>
element via javascript
In my javascript I have a variable my_url.
if my_url matches a href of simple <li>
say.. "/Campaign/CreateCampaignUrl" then I want the <li>
to look as below, the li element has class="active"..
<li class="active">
<a href="/Campaign/CreateCampaignUrl">
<i class="fa fa-th"></i> <span>Campaign Url</span>
<small class="label pull-right bg-green">new</small>
</a>
</li>
else if complex <li>
matches..
<li class="treeview active">
<a href="#">
<i class="fa fa-files-o"></i>
<span>Classify Events</span>
<span class="label label-primary pull-right">4</span>
</a>
<ul class="treeview-menu">
<li class="active"><a href="/ClassificationUI/ClassifyStandardEvent"><i class="fa fa-circle-o"></i> Standard Events</a></li>
<li><a href="/Campaign/ClassifyCampaignProperties"><i class="fa fa-circle-o"></i> Campaign Properties</a></li>
</ul>
</li>
In this case, active value attaches to class in two places..
a) the li element which has the url which matches to my_url.. in above example "/ClassificationUI/ClassifyStandardEvent".
b) the main li element which had class="treeview" has now class="treeview active"
All help is sincerely appreciated
Thanks
Upvotes: 1
Views: 729
Reputation: 1078
Since you didn't initially mention you are using jQuery I am going to give you a vanilla javascript answer:
What you want to do is select all links within the menu and run through them one-by-one. For each link you want to traverse upwards through the parentNodes until it matches the menu element and add the active class to any elements that have tagName
of "LI"
.
var my_url = '/ClassificationUI/ClassifyStandardEvent';
var menu = document.getElementsByClassName('sidebar-menu')[0];
var links = menu.getElementsByTagName('a');
function highlight(linkEl) {
var el = linkEl;
do {
el = el.parentNode;
if (el.tagName === 'LI') el.className += ' active';
} while (el !== menu);
}
var i, linkEl;
for (i = 0; i < links.length; i += 1) {
linkEl = links[i];
if (linkEl.getAttribute('href') === my_url) {
highlight(linkEl);
// break here to stop at first match
}
}
Fiddle: https://jsfiddle.net/96y4nzvm/4/
This will highlight the line items of all matching links, but if you want to limit it to the first match you can throw a break inside the if in the bottom for-loop.
EDIT: Since you have added jQuery to your list of tags here is my jQuery solution as well (same concept):
var my_url = '/ClassificationUI/ClassifyStandardEvent';
var $menus = $('.sidebar-menu');
$menus.each(function (i) {
var $menu = $menus.eq(i);
var $links = $menu.find('a[href="' + my_url +'"]');
$links.each(function (i) {
var $link = $links.eq(i);
$link.parentsUntil($menu ,'li').addClass('active');
});
});
jQuery fiddle: https://jsfiddle.net/96y4nzvm/7/
The jQuery solution has the added benefit of being able to work across multiple menus (for instance, one that shows up for desktop width, and another that shows up for mobile width).
Upvotes: 2
Reputation: 446
This should work for both simple & complex scenarios (even nested).
//var my_url = '/Campaign/CreateCampaignUrl';
var my_url = '/Campaign/ClassifyCampaignProperties';
var $menu = $('.sidebar-menu');
var addActiveClass = function(index, elem) {
var activeClass = 'active';
var $link = $(elem);
var linkSrc = $link.attr('href');
var $parent = $link.parent();
var $treeViewParent = $link.closest('.treeview');
if (linkSrc && linkSrc.indexOf(my_url) !== -1) {
$parent.addClass(activeClass);
if ($treeViewParent.length) {
$treeViewParent.addClass(activeClass);
}
}
};
// Simple & Complex
$.each($menu.find('a'), addActiveClass);
Upvotes: 0
Reputation: 2510
You can loop through all li elements and search for a child A element with the matching href, assuming jQuery :
var my_url = '/ClassificationUI/ClassifyStandardEvent';
$('.sidebar-menu>li').each(function(){
var add_active = false;
$(this).find('a').each(function(){
if ($(this).attr('href') == my_url){
if (!add_active) {
add_active = true;
}
}
});
if (add_active) {
$(this).addClass('active');
}
});
EDIT : updated code
Upvotes: 1
Reputation: 21565
You simply need to select the right elements with a selector and add the active
class:
// Simple
$("ul.sidebar-menu > li").find("a[href='/Campaign/CreateCampaignUrl']")
.parent("li").addClass("active");
// Complex
var $aSelector = $("ul.sidebar-menu > li.treeview > ul.treeview-menu > li")
.find("a[href='/ClassificationUI/ClassifyStandardEvent']");
$aSelector.parent("li").addClass("active");
$aSelector.closest("li.treeview").addClass("active");
The simple selector finds the a
tag with the href /Campaign/CreateCampaignUrl
, then goes to the parent li
and applies the active
class.
The complex selector we first find a
element that have a /ClassificationUI/ClassifyStandardEvent
under .treeview-menu
. We then add the active class to the direct parent li
, and also active
to the li
ancestor that has a treeview
class.
Upvotes: 1