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.

  1. Add the link to the topNavigation.js in your SharePoint masterpage

  1. 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.

  1. Switch the SharePoint Navigation to use the Managed Meta Data Navigation
    1. In Site Settings
    2. 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

Comments
  • BH
    Posted at 7:54 am November 18, 2020
    BH
    Reply
    Author

    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 ?

  • Jhon
    Posted at 12:26 pm March 29, 2019
    Jhon
    Reply
    Author

    How can i extend this for two level and three level

    • Tom Daly
      Posted at 12:00 am July 3, 2019
      Tom Daly
      Reply
      Author

      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.

  • Des
    Posted at 3:41 pm August 27, 2018
    Des
    Reply
    Author

    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.

    • Tom Daly
      Posted at 5:12 pm October 18, 2018
      Tom Daly
      Reply
      Author

      sorry for the delay, yes only with bootstrap v3. I have not worked with v4 as of yet.

  • Stefan Breedveld
    Posted at 9:18 am November 3, 2017
    Stefan Breedveld
    Reply
    Author

    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

    • Stefan Breedveld
      Posted at 10:10 am November 6, 2017
      Stefan Breedveld
      Reply
      Author

      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.

      • Stefan Breedveld
        Posted at 2:57 pm November 6, 2017
        Stefan Breedveld
        Reply
        Author

        My topnavigation is not visible if I change the navigationprovider to ‘SPNavigationProvider’. Is it possible to change ‘GlobalNavigationSwitchableProvider’ to ‘SPNavigationProvider’?

        • Tom Daly
          Posted at 11:23 pm February 22, 2018
          Tom Daly
          Reply
          Author

          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

      • Tom Daly
        Posted at 1:31 am February 21, 2018
        Tom Daly
        Reply
        Author

        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

      • Tom Daly
        Posted at 11:33 pm February 22, 2018
        Tom Daly
        Reply
        Author

        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.

  • Navin
    Posted at 1:21 pm October 31, 2017
    Navin
    Reply
    Author

    Tom, Can you post the end product of this code.

  • Nick
    Posted at 6:36 pm August 17, 2017
    Nick
    Reply
    Author

    Hii.. thanks for sharing.. may I take a look on how did you do in the master file?

  • Matt Rutledge
    Posted at 7:27 pm July 17, 2017
    Matt Rutledge
    Reply
    Author

    I noticed that the Sample Files links require authentication into a SharePoint site. Is there a public link to these files? Much appreciated.

  • pja
    Posted at 7:16 pm February 24, 2017
    pja
    Reply
    Author

    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

    • Tom Daly
      Posted at 7:56 pm February 24, 2017
      Tom Daly
      Reply
      Author

      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.

    • Tom Daly
      Posted at 8:58 pm February 24, 2017
      Tom Daly
      Reply
      Author

      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.

    • Tom Daly
      Posted at 9:16 pm February 24, 2017
      Tom Daly
      Reply
      Author

      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.

      • pja
        Posted at 4:06 pm March 2, 2017
        pja
        Reply
        Author

        Great – thanks for the quick response! I will download and if I run into any issues, I will post on github.

  • Leave a Reply to Tom Daly
    Cancel Reply

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