Arnab
Arnab

Reputation: 2354

adding a class attrib to html element based on certain condition javascript

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

Answers (4)

TheZanke
TheZanke

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

eblin
eblin

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);

Demo

Nested Demo

Upvotes: 0

Andrew Magill
Andrew Magill

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

Spencer Wieczorek
Spencer Wieczorek

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");

Demo

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

Related Questions