How to achieve a Mega Menu using out of the box navigation in SharePoint 2013 and jQuery.

I was looking at some requirements from a client for their new SharePoint 2013 Intranet, and one that caught my eye was desire to have Feature images on the top navigation.

The requirement was to have a dynamic top navigation, controlled using the SharePoint out of the box navigation settings, but have the ability to add a Feature image and some text to the menu. My first reaction was to think about a custom navigation control in the master page using Tokens in the navigation settings, then I got to thinking, could we do this with JQuery instead?

Here’s a brief mock-up of what they wanted to achieve.

image

So this weekend I decided to take the matter offline and have a play in my SP2013 development environment and this is what I came up with. If nothing else, it’s a great example of what you can do with some well placed tokens and a little jQuery code!

The first thing I did was take a look at the options available to us in the out of the box navigation, Not much has changed to the navigation interface in recent versions of SharePoint apart from the addition of Managed Metadata base navigation now in 2013. For this example, I’m just using the standard Navigation that forms part of the basic site structure, however there’s no real reason why you couldn’t use the same token based system in the Managed metadata.

clip_image001

In the actual navigation pane, I’ve added some standard links, and then finally a tokenised link that I’ll be using the jQuery to replace.

clip_image002

The real key with what I wanted to achieve is to make it easy for the client to be able to change the data that exists in these Big menus. So if we edit one of the tokenised options, you can see that we’re just using the default out of the box navigation fully.

We place the token in the title field, using the format ~### to denote the start of the token, then a unique identifier for this particular navigation node, and then the closing token identifier ###~. Then the url of the Image that we want to display in the URL field, and then finally the HTML that we want to display in the description field which can include full HTML.

(Note: Audiencing will still work on these menu’s too!)

clip_image003

When we save this back into the navigation, and then display our page, this is the effect we get when we hover over that particular top level node.

clip_image004

So, how did we actually achieve this? The secret is in the jQuery scripts embedded into the master page (In this demo, I’m just using a content editor web part linked to an external html file to make it easy to test and demonstrate!)

I won’t describe the CSS here as it should hopefully be fairly self explanatory and I’ve commented the jQuery code fairly well. I would say that you can and should condense any JavaScript code that you place into your production environment however for demonstration purposes, this code is spaced out and more verbose than I would write for production.. (tldr THIS IS NOT PRODUCTION CODE!)

//First we need to find all of our DOM elements that are in the Top level navigation
//and contain the start of the token field.
$("UL.dynamic span.menu-item-text:contains('~###')").each(function(){

//We then extract the token identifier, removing the ~### and ###~ from either side
var menuItem = $(this);
var parentMenuA = menuItem.closest("a");
var parentMenuUL = menuItem.closest('UL.dynamic');
var menuToken = menuItem.text().replace('~###','').replace('###~','');

//Then we extract the link to the image, and to the description field (Held in the title attribute)
var imageUrlHREF = parentMenuA.attr("href");
var linkUrlText = parentMenuA.attr("title");

//Then we hide the tokenised menu item as the user doesn't need to see it.
menuItem.hide();

//Now we add an extra class to the Parent UL to apply some CSS
parentMenuUL.addClass('featuredNavigation');

//And then wrap the original contents of the menu in an extra div to make styling them into the top right hand corner easier
parentMenuUL.wrapInner("<div class='navItemsWrapper'/>").wrapInner("<div class='navWrapper' id='" + menuToken +  "'></div>");

//Finally we build the Featured image with the data from the navigation item
var imageDiv = "<div class='navWrapperImageDiv'><img class='navWrapperImage' src='" + imageUrlHREF + "' alt='Featured Image'></img>" +
	"<div class='navWrapperImageText'>" + linkUrlText + "</div></div>";

//And then inject it into the top of the navigation object using the prepend instruction.
$('#' + menuToken).prepend(imageDiv);
});

That’s all the javascript there, though you can download the entire html file that I created for testing and embed it into a SharePoint page using a CEWP to see it in action in your environment.

Navtokeniser.html script file. (Rename from .txt)

I hope it sparked some ideas.

Paul.

3 comments

  1. Hi Paul- Thanks so much for this post. I’m trying to implement this in our SharePoint environment and am having a bit of trouble. Could you share with me the location of where you inserted the JavaScript/jQuery in the master page? Also, did you store the CSS file and HTML file separately and simply reference the JavaScript/CSS in the HTML file? I’m fairly new at programming, so forgive me if my questions seem redundant.
    Thanks!

  2. Hi Caitlin,

    In the example I linked above, I placed the jQuery/Css directly in the HTML file that was added to the content editor web part.

    In the mockup we created for the client, I added the script link and the css files directly to the masterpage. Had this gone to production I would probably have looked at wrapping them up in a packaged solution using Custom Actions. Waldek has a great solution for doing this from an App which keeps you fully supported in Office 365.

    http://blog.mastykarz.nl/deploying-custom-actions-app-model/

    A simpler approach though would be to do it in a sandbox solution (if you’re on-prem..)

    Paul

  3. Hi Paul,
    Thanks for your reply. I have successfully inserted the jQuery/CSS in the CEWP and achieved the desired results. The problem I’m having is adding it to the master page. Every time I add it, and point a composed look to the file I get the white screen that says ‘Something went wrong’. I’m fairly certain it has to do with WHERE I’m inserting the code. Also, you should know that I’m using SharePoint online, not on-prem.
    Thanks again,
    Caitlin

Leave a Reply

Your email address will not be published.

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.