The Vision:
A MegaMenu for a SharePoint portal home page
The Mission:
Make it easy to maintain. Allow rich content and sub headers as well as standard links. Factor in frequent changes without involving developers or a lengthy Dev/Test/Prod release cycle. The personal assistant of the marketing boss should be able to make changes on the fly. Instantaneous. Without any knowledge of HTML or CSS, so editing code is out. If it’s more complicated than filling in a time sheet, it won’t fly. And do all that with just the browser interface and SharePoint Designer. No Visual Studio, no custom code.
What’s a MegaMenu, anyway?
There are quite a few sites out there describing how to create impressive MegaMenus if you Bingle a bit. Rave reviews of the concept from Jacob Nielsen. Flashy sites from developers strutting their stuff. JavaScript, jQuery – the choice is yours. Most of them even work.
None of those take into account a SharePoint background, though. The MegaMenu content is always somehow “there already”, nicely configured in a nested construct of UL and LI tags, with hard-coded <A href> tags and titles. Not something the Marketing Assistant will want to get his head around if he wants to add a few items and a flashy “Hot and new” icon to a new menu entry.
So, to achieve the vision and make the mission possible, we need to come up with some practicable steps.
Here’s the plan:
- Create a SharePoint list that stores all the items to feature in the MegaMenu
- Create a view on that list with a Data View Web Part (DVWP)
- Modify the DVWP to show as nested lists instead of the standard table structure
- Apply the CSS and the jQuery
What you need:
- A SharePoint 2010 site.
- SharePoint Designer 2010
- jQuery Hover Intent plug-in: The only non-standard SharePoint elements required are the jQuery core and the library for Hover Intent. This is a variation of a JavaScript functionality that displays stuff if the mouse hovers over specific screen elements. Download the Hover Intent here: http://cherne.net/brian/resources/jquery.hoverIntent.html
- Why use Hover Intent? JavaScript mouse hover events normally fire immediately when the mouse hovers over the item. This can lead to a lot of screen flicker and a general perception of “nervous” behavior. Hover Intent waits for the mouse to pause before the event is triggered, Check out the link above for a demo of what it does. Don’t forget to download the jQuery core file.
- The CSS and jQuery script calls were originally posted at http://www.sohtanaka.com/web-design/mega-drop-downs-w-css-jquery/but this web site seems no longer available. Thanks to the WayBack machine, though, it can still be viewed in the Internet Archive and I have salvaged the MegaMenu Demo and placed a copy on my site. All credits for developing that demo go to Soh Tanaka.
The final look and feel we’re after can be experienced in the MegaMenu Demo. In my Sharepoint site, it looks like this:
Have a look around and try out the demo to see what the end product should look like. Once you’re comfortable with the concept, come back and let’s take action.
1. Create a SharePoint list for menu items
If we want the MegaMenu to be configurable, then a SharePoint List will be the most logical way to achieve that. For the sake of normalizing data, I suggest an approach with two lists.
List for MegaMenu headers
This list is called MegaMenu Headers and has three columns:
Title: — Single line of text – The MegaMenu tab title (if you use graphic files for the MegaMenu tab background, these won’t ever be visible, but they will help with the general orientation).
Order – number – the order in which the headers appear on the final page. This column will be the first sorting and grouping criterion of the mega menu. The column will be inherited by the list that stores the MegaMenu details.
CSSClass – Single line of text – This value needs to be manually created in the CSS file that formats the MegaMenu. Every header tab will have a specific width and position, defined by a CSS class. To make the formatting easier to maintain, assign the CSS class name here and then make sure that the CSS file actually has an entry that defines the properties for that class.
List for MegaMenu Content
The Headers provide the outer envelope, but the meat of the functionality will be with the individual content items of the menus. For this, we need another SharePoint List. The list is called MegaMenu Content and has these columns:
Column | Type |
MegaHeader | Lookup |
MenuRow | Number |
MenuColumn | Number |
ItemNumber | Number |
Title | Single line of text (Don’t make this required!! It will not always have data) |
MenuLink | Hyperlink or Picture |
ItemImage | Hyperlink or Picture |
ItemBody | Multiple lines of text (This is rich text) |
Published | Yes/No |
ItemWidth | Choice (the choices are: “default, 2, 3, 4”. Make the default value “default”. The code below will look out for that.) |
MegaHeader:Order | Lookup |
MegaHeader:CssClass | Lookup |
The last two columns, MegaHeader:Order and MegaHeader:CssClass are created by ticking their column names when defining the Lookup column for MegaHeader.
Now fill your list with some content. For each item, make sure you select a MegaHeader value and specify MenuRow, MenuColumn and ItemNumber. These numbers will influence the order of the items in a menu panel.
Then specify at least one of the columns Title, MenuLink, ItemImage or ItemBody If a menu item has a Title specified, it will be formatted as a h2 element. A MenuLink for an item with a title is optional.
ItemWidth is optional. Leave it at default unless you want an item to span more than one column. In that case, the first item in that column requires the ItemWidth to be set.
2. Creating a DVWP
Fire up SharePoint Designer 2010, open an existing Web Part Page or a Wiki Page and create a DVWP:
Insert > Data View > Empty Data View
In the new, empty data view, click the link to select a data source and select the list MegaMenu Content. It does not really matter which fields you select for the display, because we will gut the DVWP content and replace it with a custom XSL Template. So select a few fields and click “Insert Selected Fields as > Multiple Item View”.
By default, the DVWP only shows 10 items. Fix that by clicking “Paging > Display All Items”.
Next, click the Sort & Group icon and add these fields to the sort order:
– MegaHeader:Order
– MenuRow
– MenuColumn
– ItemNumber
3. Customising the DVWP
By default, a DVWP is displayed as a table. We need to change this to a nested list with this structure:
[html toolbar=”true” highlight=”3,4,5″]
<ul id="topnav">
<li>Header Tab
- Menu Item
- Menu Item
- Menu Item
</div></li>
<li>Next Header tab … etc</li>
</ul>
[/html]
This image shows the nested classes and divs:
red =
- or
- , depending on the data
So, let’s apply the custom template. Find the first template in the XSL and delete all template code down to the last tag. Make sure to keep the opening tags intact.
Without further ado, here is the template code that I used, starting with the tag:
[xml]
'
0
Hello,
I am trying to implement this menu, but the most that get’s rendered from the xslt in the web part is
No list or anchor tags are making it into the page. Can you tell me what I am doing wrong?
Thanks!
LikeLike
Hello GMarez,
it looks as if you meant to include an image or some samples in your post, but they did not make it.
Please make sure that the list column names and the fields referenced in the XSL match perfectly.
Before you apply the custom XSL, create a DVWP and make sure to set it to no paging and no filters. Does that render? Next, apply the groupings. Does that render?
Next, replace the standard XSL with the custom XSL I posted above, without any style sheets. What does that look like? If it does not render as a nested UL-LI-UL-LI construct, please check your column names and either adjust the column names or the XSL calls to the columns.
cheers, teylyn
LikeLike
Thanks,
It looks like some code I posted got stripped out. I have tried several times, but every time I place the XSL in the code, it stops displaying the data. There are no errors in Sharepoint, just blank. It gets as far as a UL tag with id “topnav” but the tag is empty.
I copied and pasted the names directly from your post just to make sure. I recreated the DVWP after that, which again outputs fine until I change the XSL.
Question: should there be code like this in the XSLT: [html]<a href="#" class="[/html] ?
Thank you!
LikeLike
The XSL contains code to render html tags. The pointed brackets will be interpreted as the markers of XSL tags, so they cannot be used inside an XSL tag. Instead, they must be written as
[html]> and < [/html]
It’s all a bit confusing, especially since this blogging software will parse them as brackets again. I’ve edited your post to render them as you intended them to render.
So yes, the XSL is meant to contain the [html]>[/html] and [html]"[/html] characters.
With regards to your problems getting the code to run: make sure that the column names in your list and the column names used in the XSL match perfectly. XSL is case sensitive, so CssClass and CSSClass are not the same.
I’m in the process of creating a .wsp file for download that can be installed as a solution. I’m just running into a few issue that I need to crack first.
LikeLike
Hey Teylyn,
Great solution, I’ve managed to get it working nicely with altered CSS in a page. However, when I transfer this to my master page I am getting the following error:
Object doesn’t support this property or method
Which refers to this line:
$(“ul#topnav li”).hoverIntent(config); //Trigger Hover intent with custom configurations
I’ve tried a few different solutions but I can’t get the hover intent to work. Any ideas or is there something I’m missing?
Thanks
LikeLike
Hello,
make sure you have all the required jQuery files loaded. Adjust the sample script to reflect the versions and locations of jQuery and hoverIntent that you are using. Double check.
LikeLike
Works fine, good post.
I got the additional requirement to set the headers as links to subsites. for this I made two changes to the XSLand to the lists.
First I defined a fourth column in the header list “Link” as one line of text.
This field is looked up in the content list, too.
I added this field datafields section of the DVWP: @MegaHeader_x003a_Link,MegaHeader:Link;
Than I changed the code for the header loop to embed the link:
[xml] <xsl:for-each select="$HeaderLoop">
<xsl:variable name="LinkStart" select="string(‘<a href="’)"/>
<xsl:variable name="Link"><xsl:value-of select="@MegaHeader_x003a_Link"/></xsl:variable>
<xsl:variable name="LinkStartEnd" select="string(‘" class="’)"/>
<xsl:variable name="LinkClass"><xsl:value-of select="@MegaHeader_x003a_CssClass"/></xsl:variable>
<xsl:variable name="LinkEnd" select="string(‘" >’)"/>
<xsl:variable name="LinkVar" select="concat($LinkStart,$Link,$LinkStartEnd,$LinkClass,$LinkEnd)"/>
<xsl:variable name="CloseATag" select="string(‘</a>’)"/>[/xml]
works fine.
Maybe it helps somebody
Thanks and best greetings
LikeLike
Eckhard, many thanks for that tip.
cheers, teylyn
LikeLike
This is a great article! The only thing i see missing is security trimming. Do you have any input on this? I may try to put something together over the weekend.
B
LikeLike
Hello,
If you set fine-grained permissions on individual items in the Menu Content list, these items will only show in the MegaMenu for the people who are allowed to see them, so yes, security trimming is an option.
LikeLike
Great menu! Trying to get it to work across multiple sites in the same site collection on a Publishing Site. The code seems to have to be overhauled in order for it to work with a web service. Has anyone done this yet?
LikeLike
Hello Reuben, in my company’s intranet, the MegaMenu is embedded in the Master page, and all sub-sites inherit it gracefully.
LikeLike
Hi,
I have used this webpart in my master page. I have data source list in Top level site. But when i use this same master page in subsite it does not render. Is it due to the list not available in the subsite.
will the list data in the top level site showed in all subsites
LikeLike
Hello dheena,
When the menu is used on sub-sites, you need to refer to the contributing list slightly differently. Marc Anderson has detailed the approach here: . In the Select Parameters of the web part, get rid of the List ID and the other parameters and replace them with two parameters using the list name and the list url. That way you can refer to a data source up the chain.
LikeLike
Is it possible to implement in MOSS 2007?
Please let me know.
Thanks
LikeLike
Hello Victor, I don’t have access to MOSS 2007, but I see no reason why it should not work in that version of SharePoint.
LikeLike
Hi,
I have done all your steps, I added all scripts in the master page, and the css.
but still not working.
please help.
LikeLike
Hello Mahmoud, troubleshooting SharePoint web parts that involve complex CSS and jQuery can be a bit daunting. Try to break it down into steps. First, configure the DVWP, without any CSS or jQuery in the mix. Once you see the nested list, apply the CSS. As a last step, apply the jQuery.
LikeLike
Hi, thanks for this great solution. I’m really keen to get this working in a masterpage. Initially I’ve gone down the route of getting it working in a wiki page but am running in to difficulty and would appreciate some help!
So far I’ve:
– Created the lists and kept the case the same as in your article
– Created 2 headers and a couple of items under each.
– Created a wiki page
– Added the DVWP to the page and hooked it in to the list. At this point I can see the items render fine
– Uploaded the CSS to a folder in the style library and set the site to use it in the Master Page settings.
– Uploaded the script to the same folder in the style library and modified the path.
At this point all I see is the headings I created but no items underneath. It appears as if the CSS and jquery aren’t being picked up correctly as there aren’t any styles applied and nothing happens on hover. I viewed the source and checked that the relative URL resolves when I past it in my browser. I think I may not be added the classes correctly to the MegaMenuHeaders list. If I understand correctly the hoverintent also looks for these classes? I may have missed it in the article but I’m a little confused what to put in the CSSClass section and how it works with the lookup from the content list. I have tried #sub or sub or #row or row but I’m not sure I’m on the right track?
Thank you
LikeLike
Hi again,
I’ve made some progress! For some reason the .js files were coming through as blank when I view the contents in the MS Developer Toolbar. I don’t know why this is. I managed to get it working by putting the files in the 14 hive and referencing them from the wikipage I created the DVWP on.
A couple of further questions if I may:
1. The heading orders seem to be based on alphabetical order? I have the order specified in the Headers table as Order in this case but it’s not being picked up and so to get “Heading4” to display last I had to rename to “zzHeading4”
2. Could someone please breakdown the steps to get this in a masterpage?
Thanks
LikeLike
Hi Teylyn,
Nice one!. Thanks alot for sharing this!
Could you please give me the steps on how to incorporate this to my sharepoint 2010 online master page.
Thanks in advance.
Ad
LikeLike
Hi Teylyn, I am really interested in incorporating this mega menu into our SharePoint Intranet site. Could you please elaborate a little more on this part? “The last two columns, MegaHeader:Order and MegaHeader:CssClass are created by ticking their column names when defining the Lookup column for MegaHeader.”
Thanks! 🙂
LikeLike
Hello SBDDesigner, in the MegaMenu Contents list you need to create a column called MegaHeader. This column is of the data type “Lookup” and you need to point it to the MegaMenu Headers list. Then you need to tick the boxes for the fields “Title”, “Order” and “CssClass”. The “Title” field will be the main lookup field and the other two fields will be pulled into the MegaMenu Contents list as well.
Does that make more sense?
cheers, teylyn
LikeLike
Thanks so much! That definitely helped. I have followed your other instructions but for some reason I am unable to get the hover to work. I have added the .txt file into a CEWP on the same page making sure the paths to my jquery.min.js and hover intent file are accurate to my folder location, also linked the style sheet into the page. When rendered and without the style sheet linked, I am seeing the unordered list with the and elements I added to the MegaHeader Content list, however, when I add the CSS, the LI’s disappear (as they shoud) but they do not reappear when I move my mouse over the header. What might I be missing? I appreciate any input you may have.
LikeLike
SBDDesigner,
This sounds very much like a CSS issue. The sample CSS uses images as background fill for the header items, and on top of that, image sprites, so you need to provide images that suit the CSS or use other images and adjust the CSS. Try this troubleshooting approach: Display the DVWP in IE8 without the CSS file applied. You mention that it shows all nested elements. Use the Developer Tools (F12) to check if the nested UL and LI elements have the correct classes applied (they should show similar to the first image in Step 3 of the above article). Once that is confirmed, copy the HTML code for the list, starting with the outer UL and paste it into a simple HTML file, without the SharePoint overhead. This makes testing much easier and you can test on your local browser instead of involving the server for every page load. Then apply the CSS in stages. Start with styling the outer UL and LI elements. This is about background images and correct positioning and width. Check with the Developer Tools if things don’t appear to be right and adjust the CSS. Once the MegaMenu headers show correctly, apply the CSS for the inner UL and LI elements and apply the JavaScript for the hover effect. After you have it working on the simple HTML file, apply it to the real thing.
cheers, teylyn
LikeLike
Excellent work. Thanks very much for posting this article. Everything works flawlessly!
LikeLike
Thanks, Sean. Much appreciated.
LikeLike
This is really good work, can you explain what the ItemNumber field is for, it doesn’t seem to have an affect.
Cheers, J.R.
LikeLike
The Item Number controls the order of the items inside the menu. The hierarchy is Row > Column > ItemNumber.
LikeLike
Hi teylyn,
Great stuff!
Got 2 questions:
1. what exaclty should be entered into the CSSClass column? Can you give an example for the “Home” tab
2. how to add a link to the “Home” (or any other) tab which does not contain any sub items.
Many thanks in advance!
k
LikeLike
If you want to have a “Home” tab without a drop-down, just manually add the code for that immediately before the outer-most loop.
LikeLike
Excellent teylyn, Great explanation, keep it up. I was able to implement all of it, one question though for some reason I’m not defining the lists properly so xsl is not generating classes properly, Do you mine posting the images of the lists ? I need both of them. thanks for the help.
–Naveen
LikeLike
I’m in the process of creating a clean SharePoint install on a VM. If that succeeds, I’ll build the mega menu from scratch and post the WSP. I can’t promise an ETA, since I have a day job and a family.
LikeLike
Hi Teylyn,
Thanks for posting this blog. I’m a newbie to SharePoint development. I’ve tried to follow your steps as outlined. I’ve created the lists and the DVWP per your instructions and they seem to be ok. However, I can’t get the css working. I am using the stylesheet you posted and reference it in the masterpage. It is being seen as I’m getting the green background colour. However, the headings are defaulting to other href settings. I’m assuming the problem is with the way in which I’m identifying the classes in the MegaMenu Header. Could you please tell me if I wanted to use the – ul#topnavlist a.FirstTab – how should I write this in the CssClass field? I’ve tried numerous variations but nothing seems to be working. I’d appreciate any guidance you could give me on this.
Thanks in advance
Norrie
LikeLike
The CSS file refers to images as background fills for the mega menu main tabs. You need to store these images on the server and reference them correctly in the CSS.
LikeLike
Would it be possible to get the css, xsl, js and image files zipped up that you used for the demo. I am having the same difficulty as SBDDesigner with no luck.
LikeLike
Hello Dave, I’m working on it. I cannot promise an ETA, but I’m hoping to build a clean VM and create a WSP file with everything included shortly, as soon as the pressures of my day job allow.
LikeLike
Thank you Teylyn. I really appreciate your willingness to help me understand the whole pcture.
LikeLike
Is it possible to create extra levels/layers to this Megamenu? I imagine it would involve creating a third and maybe even a fourth SharePoint list, rendering them in the nested list structure of the webpart XSL, and then changing the CSS a little? I’m a beginner, so if this is possible I’d appreciate a more detailed explanation of how I could do it. Thanks!
LikeLike
I’m stuck and confused.
I added 1 item to the Header list, using a CSS class of “topnav” because that’s what’s in your CSS.
I included the script with a CEWP and pointed it to the correct JS files.
I just get my single link without any styling. Not sure what to look for now.
LikeLike
Hi, really useful, but I have made a couple of alterations to my version and pass these on in the hope that they will be of use.
I needed to put a xsl:sort after each xsl:for-each to ensure that the required positions were obayed – otherwise I ended up with the items going into the drop downs in the order that they were entered (or modified).
I made the images clickable by wrapping them in an href,
I then disabled the @title if there is an image and a link.
LikeLike
Hello Rob, thanks for your comment. Unfortunately, any code or xsl you have posted did not make it into the comment, since the blogging platform strips out anything like code or html from comments. If you can email me the xsl, I can post it into your comment, so we all get the whole picture. My contact details are on the “About” page. Thanks for taking the time to share your approach.
LikeLike
Thanks for the enhancements. All, here are Rob’s code adjustments:
[xml]
<xsl:when test="string-length(@ItemImage) > 0 and string-length(@Title) = 0">
<!– If an image is present with no title don’t display anything on title line –>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$ItemLinkVar" disable-output-escaping="yes"/>
<xsl:value-of select="@MenuLink.desc"/>
<xsl:value-of select="$CloseATag" disable-output-escaping="yes"/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="string-length(@ItemImage) > 0">
<xsl:value-of select="$ItemLinkVar" disable-output-escaping="yes"/>
<img border="0" src="{@ItemImage}" alt="{@ItemImage.desc}"/>
<xsl:value-of select="$CloseATag" disable-output-escaping="yes"/>
</xsl:if>[/xml]
LikeLike
Hi,
Thanks for sharing this. very useful.
I have 2 questions:
1. Could you please give me an example of the content table?
I’m trying to set the rows & columns values, and it doesn’t look as I expected.
2. I want a menu with 2 rows, each row has 3 columns, and another column shared to the 2 rows, with rowspan= 2, how can I do it?
Thank you 🙂
LikeLike
Hello Chely,
re (1): the list structure is described in the blog post. Just add a few items to the list and see how they behave when some fields have values and others don’t.
re (2): The structure in the DVWP allows for colspan but not for rowspan. I don’t think that rowspan is possible, due to the way the DVWP XSL loops through each item.
LikeLike
Hi teylyn,
How to link CSS and JS files in master page to get the megamenu styles when a DVWP is inserted in master page.Can you ple let know the exact link tag.I am storing the CSS and JS files in a shared document library
Thanks in Advance
Dilip Kumar
LikeLike
Hello Dilip,
As I mention in the post, I assume that you are familiar with how to apply CSS and JS files in a master page. As a brief summary: create a new master page, copy the v4.master code into that master page and edit it. Find the tag
[xml]<head runat="server">[/xml]
Place references to the CSS and the JS files inside this tag. The order of the CSS files is important. Also, CSS files should be loaded before any JS files. I load the site collection CSS and the MegaMenu CSS with these two lines of code
[xml] <SharePoint:CssRegistration name="/Style Library/SiteCollection.css" after="corev4.css" runat="server"/>
<SharePoint:CssRegistration name="/Style Library/MegaMenu.css" after="corev4.css" runat="server"/>
[/xml]
After that and after the SharePoint Core.js is loaded, I load the JS files with these statements:
[xml] /Style%20Library/jQuery/jquery-1.6.4.min.js
/Style%20Library/jQuery/jquery.hoverIntent.minified.js
/Style%20Library/jQuery/CallMegaMenu.js
[/xml]
Save, publish and approve the new custom master page, then apply it to your site. If anything goes wrong, roll back to the out of the box v4.master page and get troubleshooting.
LikeLike
Hi teylyn,
Thanks for your quick reply.I am trying this in sharepoint 2013 online. Hope this will work with sharepoint online too.
I need some more information about the lookup columns
MegaHeader Lookup –>The lookup must be done with title field in the first list?
MegaHeader:Order Lookup–> The lookup must be done with order field in the first list?
MegaHeader:CssClass Lookup –>The lookup must be done with CSSclass field in the first list?
Thanks in advance
LikeLike
Hi teylyn,
Everything works fine but the jquery is not firing on hover i have referenced the jquery paths in master page and even tried with content editior webpart. but no luck your suggestions/help is appreciated.
Thanks
LikeLike
Hello, use Internet Explorer’s F12 key to fire up the Developer Tools. Check that all the jQuery libraries are loaded. You need the jQuery core as well as the Hover Intent. The paths in the above example lead to my favourite storage location for JS files: the Styles Library in the site collection. You may have a different storage location. Check the paths.
LikeLike
Hi teylyn,
I have custom jquey files which i have stored in my sites style library and given the correct path from my site.Still its not firing when i click site setting it seems the page lods twice.
LikeLike
I don’t know your setup, version, edition and license of SharePoint. The jQuery version I posted above definitely works with SharePoint 2010 Enterprise on premise. It’s in production at my employer and many other sites. I’m sorry, but I don’t have the means or resources to troubleshoot this for you.
LikeLike
Hi teylyn,
The sharepoint version is sharepoint 2013 its on office 365.
Thanks
Dilip Kumar
LikeLike
Hi teylyn,
Great post , i was trying to make it work since morning, header menu are loading but not loading the child menu. Do you have any working files you can send me please?
Really appreciate your help..
LikeLike