The default MVC 5 setup gives you a horrendous menu to work with and I probably could have made it look half way decent but I remembered the old SiteMapProvider
I had used many moons ago and wondered if there was anything like it available today. Turns out there is and it's available at https://github.com/maartenba/MvcSiteMapProvider. You can also do a package install...
Install-Package MvcSiteMapProvider.MVCx
...where x is the MVC version you are running.
Ok, so you got it configured and it looks pretty good but highlighting is a real PITA, I Googled for quite a while and the cleanest solution required is that you adorn one of the menu items with an 'selected
' class attribute. Well, since you can't get to the element to add the said attribute, what can we do?
In the Mvc.sitemap
file, the only thing that you are really allowed to set is the description field and when set, it overwrites the title field with what you entered in the description. So I got to thinking if I could get the current page and check it against the list of menu items and when I got a match, just set the menu items class to highlight the item.
So, given a very basic sitemap with just a few items:
<mvcSiteMapNode title="Home" controller="Home"
action="Index" description="selected">
<mvcSiteMapNode title="Pricing"
controller="Pricing" action="Index" />
<mvcSiteMapNode title="Contact"
controller="Home" action="Contact"/>
<mvcSiteMapNode title="Testimonials"
controller="Testimonials" action="Index"/>
<mvcSiteMapNode title="About"
controller="Home" action="About"/>
<mvcSiteMapNode title="Admin"
controller="Admin" action="Index" roles="Admin" />
</mvcSiteMapNode>
As you can see, I set the Home menu item to selected
and as long as it is unique, this scheme will work.
Now in your _Layout.cshtml file, add the JavaScript to do the actual work:
<script>
window.onload = function () {
setPage();
}
function setPage() {
hrefString = document.location.href ? document.location.href : document.location;
if (document.getElementById("menu") != null)
setActiveMenu(document.getElementById("menu").getElementsByTagName("a"),
extractPageName(hrefString));
}
function extractPageName(hrefString)
{
var arr = hrefString.split('/');
return arr[arr.length-1].toLowerCase();
}
function setActiveMenu(arr, crtPage)
{
for (var i=0; i < arr.length; i++)
{
if (extractPageName($($(arr[i])[0]).attr('href')) == crtPage)
{
if (arr[i].parentNode.tagName == "LI")
{
arr[i].className = "current";
}
}
}
}
</script>
Then in your styles page, set the current class to whatever highlighting you desire, mine looks like this:
.current{
color: #eab34f !important;
}
I got the code above from a site, don't remember where but I had to modify it to key on the title field and the parsing needed some work, but a lot of it came from him. Sorry dude, don't remember!