Introduction
In my last post I talked about making the SharePoint navigation render in a Bootstrap friendly way. I suggested that you could do this by changing the markup of the navigation using an ASP:Repeater to display the nodes. This works great if you’re on an on-prem environment but on Office 365 you cannot use this method because the masterpage cannot contain code blocks. If you haven’t read that it might be worth taking a look at – Bootstrap Responsive Navigation in SharePoint .
This post will demonstrate an Office 365 safe version that use JavaScript, jQuery, and REST to retrieve the navigation from SharePoint’s navigation provider. Once we have that we’ll render that out to the screen client side. With this approach we can use the out of the box Managed Meta Data navigation provider for the navigation, and we can control the exact rendering so that it fits Bootstrap’s model for a navigation bar.
The code can be downloaded directly from my git-hub account – https://github.com/tom-daly/sp2013-bootstrap-nav
Getting Started
It’s very simple to get started you only need to do a few things.
- Add the link to the topNavigation.js in your SharePoint masterpage
- In the Master Page, add the container below where the navigation will be pushed into. You will need to determine where you want the navigation to go, I’ll have a full example at the very end.
- Switch the SharePoint Navigation to use the Managed Meta Data Navigation
- In Site Settings
- Look and Feel -> Navigation
Once you complete those steps you’ll have your navigation displayed in that container.
Other Details
Changing Rendering
The rendering of the menu is defined in the renderNavigationNodes function. This is currently the format the Bootstrap likes. If you visit the Bootstrap website and take a look at the first example
http://getbootstrap.com/components/#navbar
The red box is exactly what the code is injecting. So you would wrap all that however you want it to appear. Follow the examples there are plenty out there.
2 Level Flyouts
Currently this supports only 2 levels, a top level and 1 flyout. This is just what Bootstrap v3.3.5 supports and that’s what I’m sticking with currently. If you want more levels then it’s up to you to figure that part out. It can be done and there are other 3rd parties implementing 3rd or 4th level flyouts after the fact. The code is recursive and will support as many levels as you have, you just need to handle the front end portion.
The REST Call
The query that I am using can be seen below. The /web/navigation/topbar endpoint – flat out sucks. It won’t show if a node is hidden and it didn’t behave. This is the only one I could get to work reliably.
Changing Target Container
If you want to change where the navigation goes, instead of “#my-top-navigation” then you can edit the topNavigation.js file and at the bottom change the selector to another ID preferably.
Sample Files
I have a few more sample files that might be of use to look at.
sharepoint-bootstrap-resets.css – Sample CSS file (helps with some Bootstrap/SharePoint resets)
**remove masterpage file**
Conclusion
The whole goal of this script was to have a way for an Office 365 site to use the Bootstrap navigation. Although there are still limitations it’s doable. And you don’t even necessarily need to touch the master page. You could attach the scripts and css via other methods which I won’t go in to. So if you’re an Office 365 purist who doesn’t want to customize the master page you would want to take an approach to this. I hope this helps someone out there. If there are problems with the script you can report the issues through the github page. https://github.com/tom-daly/sp2013-bootstrap-nav/issues
For the users having read permission,they are not able to view the navigation (Current Navigation). It shows empty. If contribute permission is given, navigation displays. What could be the reason ?
How can i extend this for two level and three level
it can be done but – i haven’t worked with this in a while. you’d want to make it recursive to keep drawing nodes and then modify the css to support your levels.
Attempting to implement this, however, nothing renders. Does this only work with Bootstrap V3? I am using the beta 4.0.0.2 and not seeing an output in SP2013 Online for publishing/classic sites.
sorry for the delay, yes only with bootstrap v3. I have not worked with v4 as of yet.
Hi there, your link is great but I have 2 issues.
I have a one page website with in page url’s.
So my top navigation uses url’s like ‘default.aspx#products’. When I enter this URL in the term store management it won’t work on my website. The url wants to navigate to http://www.yaguti.eu/default.aspx#products, but the actual url is http://www.yaguti.eu/Pages/default.aspx.
So when I set ‘/Pages/default.aspx#products’ as URL in the term store management it works but the first time it refresh the page and then the page navigates to the specified section.
I also uses the javascript animated scroll function for smooth scrolling between the sections. But in my javascript the scrolling will be actived by the following function:
$(‘.navbar-collapse’).find(‘.scroll a’).each(function(){
contentTop.push( $( $(this).attr(‘href’) ).offset().top);
contentBottom.push( $( $(this).attr(‘href’) ).offset().top + $( $(this).attr(‘href’) ).height() );
})
$.each( contentTop, function(i){
if ( winTop > contentTop[i] – rangeTop ){
$(‘.navbar-collapse li.scroll’)
.removeClass(‘active’)
.eq(i).addClass(‘active’);
}
})
It searches for the ‘scroll’ tag, but I cannot find the tag when I look into your code in topnavigation.js
I solved the smooth scrolling issue by setting ‘usecache’ to true in topnavigation.js.
That leaves the following problem that the first time you click on a navigation item the page refreshes and then it navigates to the in-page section. After that the navigation works fine.
I also want tested this on a subsite with a different navigation term set, but I can’t get this term set to work. The subsite keeps showing the navigation term set from the topsite. Can I use a different navigationProvider? The seattle masterpage (what is use as masterpage for the admin section) is showing the right term set navigation that I created for the subsite.
My topnavigation is not visible if I change the navigationprovider to ‘SPNavigationProvider’. Is it possible to change ‘GlobalNavigationSwitchableProvider’ to ‘SPNavigationProvider’?
yes you could switch the provider in the code or add your own to the list there and then change parts of the code that use the navigation provider “config.navigationProvider.global”
https://www.screencast.com/t/8WIMSGlFR1mo
Thank you for the feedback. I’m not getting alerted for comments so it took me time to see this.
If you want a different navigation on subsites, then you won’t be able to set usecache: true. That would lock it in.
usecache thinks that the top nav would be the same in every site. If you turned it off ‘usecache’ then you can set the navigation provider in the individual site to use something other than the parent and the navigation would reflect properly.
I can take a look the issue with the #links and see if there is anything I can do there. ‘usecache’ could potentially be changed to check if the site is using custom navigation and then use cache or not but I didn’t have any plans to make that update. That’s the second time I’ve had that request so I might make it happen. I’ll give this a try tomorrow 2/21/2018
Ok I understand, so you don’t want the page to redirect… you only want it to change the # hash and scroll in the page.
I would think that you might be able to trick it so if you are on default.aspx, automatically redirect to default.aspx# or set your home page the default.aspx# … then your links won’t redirect you but just stay on the page. Otherwise I don’t see how you are going to avoid that first refresh.
>>That leaves the following problem that the first time you click on a navigation item the page >>refreshes and then it navigates to the in-page section. After that the navigation works fine.
Tom, Can you post the end product of this code.
the end code is on github https://github.com/tom-daly/sp2013-bootstrap-nav
Hii.. thanks for sharing.. may I take a look on how did you do in the master file?
I noticed that the Sample Files links require authentication into a SharePoint site. Is there a public link to these files? Much appreciated.
thanks for the feedback – I’ll try to fix them this week. the most important is the boostrap resets for sharepoint. I have a copy in my dropbox right now.
https://www.dropbox.com/s/e5mjuz7vjm5y9ta/sharepoint-bootstrap-reset.css?dl=0
moved that file -> https://github.com/tom-daly/sp2013-bootstrap-nav/blob/master/src/Style%20Library/sharepoint-bootstrap-resets.css
[…] Source […]
Hello there, I followed the instructions above and got it working on the first try on our 2013 site. Thank you for this.
While everything looks great, I did notice an issue. I have a top level menu item of “Products”. Clicking on that opens the menu and displays “Product A” and “Product B” which are child terms beneath “Products”. This is correct as defined by my term store. The friendly links of the two products in the menu should be “/products/product-a” and “/products/product-b”. Instead, the hyperlink is being rendered as “/product-a” and “/product-b” respectively, which results in 404s. Do you have any thoughts on why this might be happening?
Thanks
Thanks for the feedback. The script is looking for the Simple Link. let me see if the Friendly link is available and i’ll let you know.
I’ve recreated what you’ve described and I can see the issue that you are reporting. I am working on a fix at the moment.
I believe that it’s fixed. Please update the script with the latest version v0.4 https://github.com/tom-daly/sp2013-bootstrap-nav
If you find another issue with the code please report it on github.
thanks again for using and getting back to me! I appreciate it.
Great – thanks for the quick response! I will download and if I run into any issues, I will post on github.