SharePoint – A Global Navigation Solution Across Site Collections
Guest Author: Peter Allen
BitsOfSharePoint
Ever want to have an easier way to have a global navigation that spans across site collections? SharePoint provides a solution for global navigation within a site collection and it works well. But when you architect SharePoint to have multiple web apps and site collections you do not have any easy solution to create a global navigation system to span those repositories. You would have to recreate your global navigation on each site collection. And any changes to the global navigation would mean that you would have to go to each site collection to make the change…ouch!!! There has got to be a better solution.
Thanks to Marc Anderson and Michael Greene who have created solutions that inspired me to explore solving this problem. Marc Anderson created SPServices, which is a jQuery library for SharePoint Web Services. I am beginning to understand the power of his solution. Then Michael Greene created a solution, Application Wide Quick Launch Control, where you can change or append the Quick Launch on SharePoint sites. Michael’s solution used Marc’s SPServices and jQuery.
Based on what these two have done, I then looked into how we could apply this to the Top Navigation found in SharePoint.

My goal was to do the following:
- Be able to add a tab at the beginning or end of the Top Navigation bar.
- Create a pull down to maximize space.
- Ever see a top nav bar with too many tabs, ouch.
- Pull down items are pulled from a standard SP Links list.
- Imagine being able to add an item to a list and it is then apart of the top navigation across site collections, yes!
- WSS does not give us the ability to have a pull down, lets change that.
- Ability to order and group pull down items.
- Organization is critical to ease of use.
- Grouping Headers can be links or not.
- Navigation tab and pull down changes with site theme.
- Tabs can be links or not.
What is the end product going to look like, well, something like this. Where we have added a tab called “Services” with a pull down that is grouped. This is a WSS site, where this is not possible out of the box.

And we are pulling this from a list. Take a look at the TopNav links list below. You can see the grouping and ordering is working as well.

Now lets walk through what we have to do to get the above results.
Components needed:
- SharePoint Resource Site
- SPServices by Marc Anderson
- jQuery
- SharePoint Designer to edit Master Pages
- SharePoint Links List
- Solution Code
1) SharePoint Resource Site
I recommend that if you do not already have a site collection devoted to scripts and lists that will be accessible by all, that you create one. This site collection will allow you to have document library where you can house your scripts like jQuery and SPServices. It will also allow you to create lists as needed for example the one we will create to manage the pull down items in our tab.
So there should be a site collection where we house the below files and list and that has permissions set to all authenticated members as read only. For purposes of this article I will call this site collection Resources. I wrote an article along these lines and here it is: http://www.bitsofsharepoint.com/BlogPoint/Lists/Posts/Post.aspx?ID=29
2) SPServices by Marc Anderson
We need to download the SPServices file that Marc Anderson has put together. You can find it here: http://spservices.codeplex.com/ This file will be used by the script for this solution, so this will need to be added to the document library where you keep scripts. In my case it would go into the document library in my Resources site collection.
Recommendation is to change the name of the file name so that it does not have a version number and should look like this, “jquery.SPServices-latest.min.js”. This will allow you to update in the future to Marc’s latest version without having to go back to each master page and change to the new version name.
3) jQuery
There are two ways to work with a jQuery file. You have a choice of downloading the latest version and putting it in scripts document library or you can point to Google’s version which will always be the latest version. This is a choice that you will make. You can download jQuery from here: http://jquery.com/
I would then add this script to me document library in my Resources site collection.
4) SharePoint Designer to edit Master Pages
You will need to have access to SharePoint Designer and be able to edit the Master Pages on the sites you want the global navigation tab to show up on. When you edit a master page you will want to add the following code between the <header></header> tags as diagramed below.

Here is the code you will need to add to each master page. Make sure that the URL’s point to where you have the files housed. They do need to be absolute URL’s, as you will be adding this code across site collections, web apps and even servers.
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script type="text/javascript" src="http://yoursite/SiteCollection/LibraryName/jquery.SPServices-latest.min.js"></script> <script type="text/javascript" src="http://yoursite/SiteCollection/LibraryName/topnavigation.js"></script>
For example if I put “jquery-latest.js”, “jquery.SPServices-latest.min.js”, and “topnavigation.js” in my Resoures site collection in the document library called ScriptsLibrary, then it would look like this:
<script type="text/javascript" src="http://www.bitsofsharepoint.com/Resources/ScriptsLibrary/jquery-latest.js"></script> <script type="text/javascript" src="http://www.bitsofsharepoint.com/Resources/ScriptsLibrary/jquery.SPServices-latest.min.js"></script> <script type="text/javascript" src="http://www.bitsofsharepoint.com/Resources/ScriptsLibrary/topnavigation.js"></script>
5) SharePoint Links List
Now to create the ease of updating and managing the content in the pull down for the tab, we will need to have a list where the solution can pull the links from. But we also need to create some organization and groupings. So will will create a links list and add some additional columns.
In my Resources site collection I will create a list called TopNav, you are free to name it what you like. This TopNav list will be a Links list. Once created we need to add a couple of other columns:
- Group – This column will be used to group the links together. So all “Help” links will be together and all “Features” links will be together.
- This is a text field or it can be a choice field if you know all the groups.
- LinkType – This column will be used to identify what type of link it is.
- This is a Choice column.
- We have three choice types and each will cause the pull down to display the link in different way:
- Link – This will display the item as a link within the group.
- Header – This will display the item as a header without a link.
- Header Link – This will display the item as a header with a link.
- (Header and Header Link look them same, but act differently)
Next you will want to change the default All Links view to the following:
- Sort – Change the following:
- All users to order items in this view, set to “No”.
- Sort by “LinkType” in “ascending order”.
- And Sort by “URL” in “ascending order”.
- Group By – Change the following:
- Group by to “Group” in “ascending order”.
- Show grouping as “Expanded”.
This new view will be the way the items show in the pull down for the global navigation. So you can play with the view here to sort and group it as you wish.
Here is an example of what it should look like once you have several links listed.

Almost there……yeah.
6) Solution Code
Ok, now for the code that will make this all work together. There is a file called topnavigation.js that we will need to be created and edited to make it work in your environment.
In my case it would go into the document library in my Resources site collection.
To make this script work you will need to provide several pieces of data which are listed out below.
- [tabSide] – Specify either ‘append’ or ‘prepend’. This will indicated if the new tab will go before or after the default tabs.
- Tab front Example: ‘prepend’
- Tab End Example: ‘append’
- [titleTabName] – Specify a name for the tab, this will be displayed in the tab.
- Tab Name Example: ‘Intranet’
- [urlTab] – Specify a link only if you want the tab to be clickable, otherwise leave blank with two quotes, ”.
- Link Example: ‘http://www.google.com‘
- No Link Example: ”
- [listName] – Specify the name of the list for the pull down.
- List Name Example: ‘Links’
- [listSiteUrl] – Specify the url of the site where the list is located. URL needs to be of the site location NOT of the list location.
- Incorrect Example: ‘http://www.intranet.com/SiteName/List/ListName/‘
- Correct Example: ‘http://www.intranet.com/SiteName/‘
All above variables will then be constructed as follows, make sure that each field has a ‘ at the beginning and end of each.
- Construct:
- extendedTabs(’[tabSide]‘,’[titleTabName]‘,’[urlTab]‘,’[listName]‘,’[listSiteURL]‘)
- Example:
- extendedTabs(’append’,'Projects’,’http://www.sites.com/Projects/’,'Projects’,'http://www.site.com/Resources/‘);
- This example adds:
- A tab at the end
- A link for the Tab to the Project site
- The list for the pull down is called Projects
- The list resides in the Resources site.
You can have multiple extendTabs like so:
extendedTabs(’append’,'Projects’,”,’Projects’,’http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/‘);
extendedTabs(’append’,'Team Sites II’,’http://www.google.com’,'Team Sites’,’http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/‘);
extendedTabs(’prepend’,'Intranet II’,’http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/default.aspx‘,‘Links’,'http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/‘);
There will be three tabs added, with one added the to the front and two added to the back.
Placement of your extendedTabs will dictate the order the tabs are displayed.
Here is the code to add to the topnavigation.js file or you can download the topnavigation.js file from here. http://www.bitsofsharepoint.com/ExamplePoint/CodeExamples/topnavigation.js
$(document).ready(function(){ /* Extended Tabs by Peter Allen Version 1.0 5/3/2010 Purpose: Add a tabs to the beginning (prepend) or end (append) of the default SharePoint Top Navigation tabs. Script Setup: To make this script work you will need to provide several pieces of data which are listed out below. [tabSide] - Specify either 'append' or 'prepend'. This will indicated if the new tab will go before or after the default tabs. Tab front Example: 'prepend' Tab End Example: 'append' [titleTabName] - Specify a name for the tab, this be displayed in the tab. Tab Name Example: 'Intranet' [urlTab] - Specify a link only if you want the tab to be clickable, otherwise leave blank with with two quotes, ''. Link Example: 'http://www.google.com' No Link Example: '' [listName] - Specify the name of the list for the pull down. List Name Example: 'Links' [listSiteUrl] - Specify the url of the site where the list is located. URL needs to be of the site location NOT of the list location. Incorrect Example: 'http://www.intranet.com/SiteName/List/ListName/' Correct Example: 'http://www.intranet.com/SiteName/' All above variables will then be constructed as follows, make sure that each field has a ' at the begining and end of each. Construct: extendedTabs('[tabSide]','[titleTabName]','[urlTab]','[listName]','[listSiteURL]') Example: extendedTabs('append','Projects','http://www.sites.com/Projects/','Projects','http://www.site.com/Resources/'); This example adds a tab called Projects at the end, tab links to the Project site, the list for the pull down is called Projects and the list resides in the Resources site. You can have multiple extendTabs like so: extendedTabs('append','Projects','','Projects','http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/'); extendedTabs('append','Team Sites II','http://www.google.com','Team Sites','http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/'); extendedTabs('prepend','Intranet II','http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/default.aspx','Links','http://www.bitsofsharepoint.com/ConsultingPoint/ClientPoint/snc/'); Placement of your extendedTabs will dictate the order the tabs are displayed. */ // Place your extendedTabs below: extendedTabs('append','Projects','http://www.site.com/site/default.aspx','Projects','http://www.site.com/site/'); var i = 1; function extendedTabs(tabSide,titleTabName,urlTab,listName,listSiteURL) { var titleTabID = 'zz1_TopNavigationMenun' + titleTabName.replace(/[-' ']/g,''); var showTabPD = titleTabID + 'Show'; var showTabAppend = titleTabID + 'Append'; if (urlTab != '') { var urlTabShow = 'href=' + urlTab; } else { var urlTabShow = ''; } var tableRow = ' <td id="' + titleTabID + '" onkeyup="Menu_Key(event)" onmouseout="Menu_Unhover(this)" onmouseover="Menu_HoverRoot(this)"><table width="100%" cellspacing="0" cellpadding="0" border="0" class="ms-topnav zz1_TopNavigationMenu_4"><tbody><tr id="mouse"><td style="white-space: nowrap;"><a ' + urlTabShow + ' style="border-style: none; font-size: 1em;" class="zz1_TopNavigationMenu_1 ms-topnav zz1_TopNavigationMenu_3">' + titleTabName + '</a><td valign="top" style="width:0pt;" ><img style="border-style:none; vertical-align:top;" alt="" src="/_layouts/images/menudark.gif"></td></tr></tbody></table><div style="position:absolute;height: 0px;z-index:1;"><div id="' + showTabPD + '" class="zz1_TopNavigationMenu_8" style="display:none;position:relative;top:0px; clip: rect(auto, auto, auto, auto);z-index:1;"><table cellspacing="0" cellpadding="0" border="0" style="top: 0px;" id="' + showTabAppend + '"></table></div></div></td>'; if (tabSide == 'prepend') { $('table#zz1_TopNavigationMenu').children().children().prepend(tableRow); } else { $('table#zz1_TopNavigationMenu').children().children().append(tableRow); } $().SPServices({ operation: "GetListItems", webURL: listSiteURL, listName: listName, completefunc: function (xData, Status) { $(xData.responseXML).find('[nodeName=z:row]').each(function() { var URLdataTN1 = $(this).attr("ows_URL").split(','); var linksTN1 = $(this).attr("ows_LinkType"); if (linksTN1 == 'Header') { $('#' + showTabAppend).append('<tr id="zz1_TopNavigationMenun' + i + '" onkeyup="Menu_Key(event)" onmouseout="Menu_Unhover(this)" onmouseover="Menu_HoverDynamic(this)"><td><table cellspacing="0" cellpadding="0" border="0" width="100%" class="ms-topNavFlyOuts zz1_TopNavigationMenu_7 ms-topNavFlyOutsHover"><tbody><tr><td style="white-space: nowrap; width: 100%;"><a style="border-style: none; font-size: 1em;" class="zz1_TopNavigationMenu_1 ms-topNavFlyOuts zz1_TopNavigationMenu_6 ms-topNavFlyOutsHover"><strong>' + URLdataTN1[1] + '</strong></a></td></tr></tbody></table></td></tr>'); i++; } else if (linksTN1 == 'Header Link') { $('#' + showTabAppend).append('<tr id="zz1_TopNavigationMenun' + i + '" onkeyup="Menu_Key(event)" onmouseout="Menu_Unhover(this)" onmouseover="Menu_HoverDynamic(this)"><td><table cellspacing="0" cellpadding="0" border="0" width="100%" class="ms-topNavFlyOuts zz1_TopNavigationMenu_7 ms-topNavFlyOutsHover"><tbody><tr><td style="white-space: nowrap; width: 100%;"><a style="border-style: none; font-size: 1em;" href="' + URLdataTN1[0] + '" class="zz1_TopNavigationMenu_1 ms-topNavFlyOuts zz1_TopNavigationMenu_6 ms-topNavFlyOutsHover"><strong>' + URLdataTN1[1] + '</strong></a></td></tr></tbody></table></td></tr>'); i++; } else { $('#' + showTabAppend).append('<tr id="zz1_TopNavigationMenun' + i + '" onkeyup="Menu_Key(event)" onmouseout="Menu_Unhover(this)" onmouseover="Menu_HoverDynamic(this)"><td><table cellspacing="0" cellpadding="0" border="0" width="100%" class="ms-topNavFlyOuts zz1_TopNavigationMenu_7"><tbody><tr><td style="white-space: nowrap; width: 100%;"><a style="border-style: none; font-size: 1em;" href="' + URLdataTN1[0] + '" class="zz1_TopNavigationMenu_1 ms-topNavFlyOuts zz1_TopNavigationMenu_6">' + URLdataTN1[1] + '</a></td></tr></tbody></table></td></tr>'); i++; } }); } }); $('#' + titleTabID).mouseover(function(){ $('#' + showTabPD).show(); }); $('#' + titleTabID).mouseleave(function(){ $('#' + showTabPD).hide(); }); } });
OK, now lets pull this all together.
- Document Library where the following is housed:
- jquery-latest.js
- jquery.SPServices-latest.min.js
- topnavigation.js”
- A links list created called TopNav
- Added columns:
- Group
- LinkType
- Changed All Links View
- Modified topnavigation.js file as outlined.
- Add a extendedTab call.
- Edited masters pages with SharePoint Designer to add the three lines of code.
You should now be seeing something like this.

Here is a working example: http://www.bitsofsharepoint.com/ExamplePoint/Navigation/default.aspx
Hope this helps.
Guest Author: Peter Allen
BitsOfSharePoint
Peter Allen is President of BitsOfSharePoint Consulting LLC, based in Sacramento, CA. He has worked in the technology field for 15 years creating and deploying solutions in Healthcare, financial, construction, municipalities, telecom, and engineering firms. He provides solutions that address site architecture, taxonomy, useability and findability. He also speaks at SharePoint community events and blogs at his SharePoint site http://www.bitsofsharepoint.com.
- SharePoint - A Global Navigation Solution Across Site Collections
- SharePoint – A Global Navigation Solution Across Site Collections – Version 2.0 Primer and Deployment
- SharePoint - A Global Navigation Solution across Site Collections – Version 2.0 Solution
Peter,
My personal opinion is that using Marc’s library just to pull items from a list is an overkill. The same comment would apply to Michael Greene’s example.
I’d be interested in Marc’s feedback on this.
Christophe
Christophe:
I’m not really sure what you mean by your overkill comment. What would you suggest as the alternative approach?
Frankly, I *might* use my other hammer to accomplish something like what Peter’s going above: the DVWP. But I’d still want the underlying data to come from a list. Which approach someone chooses can be driven by many factors, of course, including what tools they are most comfortable using. (We all know what the .NET guys would do.)
M.
I think Christophe’s point was more that loading and using your library just for a simple query call was overkill. In reality that web service could have been called with some JavaScript, or it could be done the .NET way.
When you look at a solution in this context it’s easy to focus just on what’s in front of you and not think about how it integrates with everything else, or what other things are going on in the deployment. I can’t speak to Peter’s deployment, but in my application we’re using many functions of Marc’s library alongside this portion of it. It wasn’t deployed purely for a single content query.
Mike
I think Michael said it well. By adding jQuery and SPServices to the Master Pages across site collections we build the infrastructure to easily add solutions that require either services.
I would say that while you are modifying the Master Page you could add a script,js file for future use to load scripts files without having to edit each Master Page going forward. jQuery has a nice $.getScript which is shorthand ajax call for a script. This would provide an easy way to roll out a script across site collections without having to modify all the Master Pages, but this is getting further from the solution above and more into architecture.
Mike, that’s exactly what I meant, you could for example write a JavaScript or jQuery AJAX call from scratch (or copy/paste the one from Jan Tielens’ blog…).
I have to agree with the above comments, it all depends on the context of your deployment.
Christophe:
There certainly could be performance considerations, as well. I’d certainly start with my library for ease of implementation and pare it back if there was some sort of bottleneck. Since SPServices is open source, you’re also welcome to unbundle just the function(s) you need. I like to think that my implementation of the Web Services calls are pretty lean, but you do need to impose the overhead of jQuery to use them. Straight JavaScript would alleviate some of that, but then you might have a maintainability issue.
M.
@Marc: sorry, I realize my first comment was not clear.
btw a DVWP wouldn’t work here as the navigation is meant to span across site collections. But you’re right, there are other options. And storing the links in a SharePoint list with grouping is definitely the way to go.