Skip Ribbon Commands
Skip to main content

:

> Posts > Tabbed Web Parts in SharePoint 2013 / Office 365
April 24
Tabbed Web Parts in SharePoint 2013 / Office 365

I think many would agree with me that one of the best things to ever happen to SharePoint 2007 in terms of an improved user experience was Christophe’s EasyTabs over at Path To SharePoint.  This script turned several web parts that were stacked on top of each other into a much more elegant tabbed view.

And there was much rejoicing.

Christophe updated this script to work for SharePoint 2010 as well. I know countless people who have used it with great success.  However, recently I needed to use EasyTabs for a SharePoint 2013 site and discovered that there was not a 2013 version and the 2010 version did not appear to work. So, what’s a jQuery hack to do but write my own solution? Although not quite as eloquent as Christophe’s solution, it gets the job done. The remainder of this blog walks you through what I did and how you can do it as well.

<update>

Christophe contacted me to me know there's actually a replacement for the Easy Tabs in SP 2013. For more information see these links:

The free version of the SPELL Nav is a replacement for the Easy Tabs. The paid version adds more features, including an edit menu.

</update>

jQuery UI to the rescue

image 

I always try to take advantage of those who came before me, and the jQuery UI tabs do all the heavy lifting of creating tabs for me. Now I just need to write a script to find the Web Parts that I want to put in a tabbed view and move their content into the tabs.

Like I said, not quite as elegant

Unlike Christophe’s solution, my script doesn’t take all the web parts in a web part zone and turn them into a tabbed view. Instead, you specify the titles of the web parts that you want to appear in the tabbed view. This is kind of cool because you can pull web parts from different zones into a tabbed view, but it does require you actually do some typing… sorry… 

The Script

Below is the script I used for putting SharePoint 2013 web parts into a jQuery UI tabbed view.

<!-- Reference the jQueryUI theme's stylesheet on the Google CDN. Here we're using the "Start" theme --> 
<link  type="text/css" rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/themes/start/jquery-ui.css" /> 
<!-- Reference jQuery on the Google CDN --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- Reference jQueryUI on the Google CDN --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script> 

<style type="text/css">
</style>

<script type="text/javascript">
     jQuery(document).ready(function($) {
         $(".s4-wpcell").hide();
         $(".s4-wpcell-plain").hide();
         //Put the Web Part Title for all the Web Parts you wish
         //to put into the tabbed view into the array below.
         setTimeout(function() {
            HillbillyTabs(["Issue","Image Viewer","Time","Speakers","States","Cities","SlideShow"]);
        }, 0);

    });

function HillbillyTabs(webPartTitles)
    {
        for(index in webPartTitles)
        {
            var title = webPartTitles[index];
            $("#HillbillyTabs").append('<li><a href="#Tab'+index+'" id="TabHead'+index+'" onclick="SetActiveTab(this.id);">'+
title+'</a></li>').after('<div id="Tab'+index+'"></div>');
            $("span:contains('"+title+"')").each(function(){
                if ($(this).text() == title){
                   var webPart = $(this).hide().closest("span").closest("[id^='MSOZoneCell_WebPart']");
                   if ($(webPart).contents().html() != undefined)
                   {
                           webPart = $(webPart).contents();
                   }
                   $("#Tab" + index).append((webPart));
            }});
        }
        $("#tabsContainer").tabs();
        $(".s4-wpcell").show();
         $(".s4-wpcell-plain").show();

    }
</script>
<div id="tabsContainer"><ul id="HillbillyTabs"></ul></div>

The script looks for the Web Parts specified by the Web Part Titles passed into the “HillbillyTabs” function. A jQuery UI tab is created for each Web Part. The title for the tab is the Title of the Web Part. Then the contents of that Web Part are moved into the created tab’s content area. Finally, the title of the Web Part is hidden since the tab contains the Title.  That’s all there is to it.

To use the script

To use the scripts, follow these steps:

  1. Upload the above script to a location you can reference in your site (like possibly the Site Assets Document Library)
  2. Create a Web Part Page.
  3. Add the various Web Parts onto the page that you want to appear in the tabbed view.
  4. Add a Content Editor Web Part to the page.
  5. Edit the above script so that the call to the “HillbillyTabs” function contains the titles of the Web Parts you wish to appear in the tabbed view. For instance. If you had a Web Part with the title “Projects” and another Web Part with the title “Tasks”, the section of script you would change would look like this:
    jQuery(document).ready(function($) {
            HillbillyTabs(["Projects","Tasks"]);
        });
  6. Link the above script to the Content Editor Web Part.

Ta and Da.. you should now see your Web Parts in a tabbed view.  Here’s a quick video that shows the above steps in action.

image 

Persisting tabs

One thing you will notice is that the active tab is not persisted should the page reload. This may not be a big deal, but I know some people find it annoying.  To get around this issue I updated the above script to the script below to use cookies to make the currently selected tab stay selected should the user do something that causes the page to reload. Just follow the same instructions as above but replace the script with the one below.

<!-- Reference the jQueryUI theme's stylesheet on the Google CDN. Here we're using the "Start" theme --> 
<link  type="text/css" rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/themes/start/jquery-ui.css" /> 
<!-- Reference jQuery on the Google CDN --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- Reference jQueryUI on the Google CDN --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script> 

<script type="text/javascript">
     jQuery(document).ready(function($) {
        $(".s4-wpcell").hide();
         $(".s4-wpcell-plain").hide();
         //Put the Web Part Title for all the Web Parts you wish
         //to put into the tabbed view into the array below.
        HillbillyTabs(["Web Part Title 1","Web Part Title 2"]);
        //show persisted tab        
        ShowActiveTab();

    });

    function HillbillyTabs(webPartTitles)
    {
        for(index in webPartTitles)
        {
            var title = webPartTitles[index];
            $("#HillbillyTabs").append('<li><a href="#Tab'+index+'" id="TabHead'+index+'" onclick="SetCookie(this.id);">'+
title+'</a></li>').after('<div id="Tab'+index+'"></div>');
            $("span:contains('"+title+"')").each(function(){
                if ($(this).text() == title){
                   var webPart = $(this).hide().closest("span").closest("[id^='MSOZoneCell_WebPart']");
                   if ($(webPart).contents().html() != undefined)
                   {
                           webPart = $(webPart).contents();
                   }
                   $("#Tab" + index).append((webPart));
            }});
        }
        $("#tabsContainer").tabs();
        $(".s4-wpcell").show();
         $(".s4-wpcell-plain").show();

    }



    function SetCookie(id)
    {
           var date = new Date();
           //make the cookie expire in 5 minutes
           date.setTime(date.getTime()+(300*1000));
           var expires = "; expires="+date.toGMTString();
           document.cookie = "ActiveTab="+id+expires+"; path=/";
    }
    
    function ShowActiveTab()
    {
        var name = "ActiveTab";
        var cookieArray = document.cookie.split(";");
        for (index in cookieArray)
        {
            var keyValuePair = cookieArray[index].split("=");
            var key = keyValuePair[0];
            key  = key.replace(/^\s+|\s+$/g, "");
            if (key == name)
            {
                var value = keyValuePair[1];
                $("#" + value).click();
                return;
            }
        }
    }


</script>
<div id="tabsContainer"><ul id="HillbillyTabs"></ul></div>

<UPDATE>

“Breaking Layouts” or Some Web Parts not appearing properly

A few people have indicated that they have a problem with the “layouts breaking” or a web part not being displayed properly for some web parts in a tab, I’ve been able to track this down to scripts executing after jQuery.ready() to do things like place items in calendars. To alleviate this problem I added a delay to the execution of the tabs functionality to give these other scripts time to execute. If you are having a problem with shifting layouts, try using the below script.  The script delays for 800ms, if you find this id not long enough try increasing this value in the “setTimeout” function call below.  I’m not enamored with this solution, and if a better solution comes to mind I’ll be sure to let you know!

<!-- Reference the jQueryUI theme's stylesheet on the Google CDN. Here we're using the "Start" theme --> 
<link  type="text/css" rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/themes/start/jquery-ui.css" /> 
<!-- Reference jQuery on the Google CDN --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- Reference jQueryUI on the Google CDN --> 
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.0/jquery-ui.min.js"></script> 

<script type="text/javascript">
     jQuery(document).ready(function($) {
          $(".s4-wpcell").hide();
         $(".s4-wpcell-plain").hide();

         //Put the Web Part Title for all the Web Parts you wish
         //to put into the tabbed view into the array below.
        setTimeout(function() {
            HillbillyTabs(["Web Part 1","Web Part 2", "Web Part 3"]);
        }, 800);

    });
    

    function HillbillyTabs(webPartTitles)
    {
        for(index in webPartTitles)
        {
            var title = webPartTitles[index];
            $("#HillbillyTabs").append('<li><a href="#Tab'+index+'" id="TabHead'+index+'" onclick="SetCookie(this.id);">'+
title+'</a></li>').after('<div id="Tab'+index+'"></div>');
            $("span:contains('"+title+"')").each(function(){
                if ($(this).text() == title){
                   var webPart = $(this).hide().closest("span").closest("[id^='MSOZoneCell_WebPart']");
                   if ($(webPart).contents().html() != undefined)
                   {
                           webPart = $(webPart).contents();
                   }
                   $("#Tab" + index).append((webPart));
            }});
        }
        $("#tabsContainer").tabs();
        $(".s4-wpcell").show();
         $(".s4-wpcell-plain").show();

    }

    function SetCookie(id)
    {
           var date = new Date();
           //make the cookie expire in 5 minutes
           date.setTime(date.getTime()+(300*1000));
           var expires = "; expires="+date.toGMTString();
           document.cookie = "ActiveTab="+id+expires+"; path=/";
    }
    
    function ShowActiveTab()
    {
        var name = "ActiveTab";
        var cookieArray = document.cookie.split(";");
        for (index in cookieArray)
        {
            var keyValuePair = cookieArray[index].split("=");
            var key = keyValuePair[0];
            key  = key.replace(/^\s+|\s+$/g, "");
            if (key == name)
            {
                var value = keyValuePair[1];
                $("#" + value).click();
                return;
            }
        }
    }


</script>
<div id="tabsContainer"><ul id="HillbillyTabs"></ul></div>

</UPDATE>

 

Parting thoughts

I don’t love the way I search for the appropriate Web Part. Unfortunately there is no attribute that only contains the title of the Web Part.  There is a title attribute, but it cannot be depended upon to only contain the Web Part Title (I found this out the hard way when SharePoint decided to create a Web Part Description for me that I could not delete. Thanks SharePoint).

The above solution works in either On Premise SharePoint 2013 or Office 365. It may even work with SharePoint 2010, but I have not bothered to try. Regardless, if someone smarter than me knows how to make the script more performant, I’m all ears… err.. eyes?

Thanks once again for allowing me to waste part of your day!  Cheers!

Comments

Very Nice

I love it Mark. Simple but elegant. It looks great too. Just out of curiosity, is there a session state that you can work with on O365? I haven't worked with O365 much, but I was just curious if you know if you have that option to save selected tabs rather than cookies.
 on 4/24/2013 7:39 PM

Work great in 2010 too

It looks very nice but when you right click inserted web part become out of the tabs and never get back into the tabs until you open site again. Any help?
 on 5/16/2013 2:35 PM

Need more information?

I'm not sure what you mean by "right click inserted web part become out of the tabs".  I right clicked on the tabs from my 2010 demo:

http://www.sharepointhillbilly.com/demos/SitePages/Tabs.aspx

And the web part does not come out of the tabs? I think I'm probably just not understanding the steps you are taking to see the problem.  Do you mind giving me step by step instructions on how to reproduce the error? Can you reproduce it from my demo url above??

thanks!
EMS\markrackleyNo presence information on 5/16/2013 3:58 PM

Nice

I thought I'd give this a try in SP2010 and it works ok until you stick a calendar webpart on the page, then everything get's shrunk up to a small size.

I'll let you know what i find.
 on 5/20/2013 8:31 AM

Awesome!

Have you got it to work on a Web Part page that is not Full Column Page? i.e. with left and right web part zones
 on 5/20/2013 10:26 AM

How to Implement Tabs in sharepoint2010 edit form.aspx

Hi i need to implement same concept in sharepoint2010 editform is it possible to implement i tried this one but not succeed please can you give a example for this it will be helpful to me thanks in advance.
 on 5/21/2013 8:03 AM

Working in edit form...

It looks like to get it working in the Edit form you have to edit the web part properties and change the Chrome Type to "Title Only" for the web parts because it appears the Default Chrome for the edit form is to remove the Title.  The title is necessary or the script has no way of finding the web part.

Good luck!
Mark
EMS\markrackleyNo presence information on 5/21/2013 8:30 AM

CQWP

Hi Mark,

Tried your tabbed script with SP 2010 and content query WP.  It's not loading the content...any ideas?

Thanks!
 on 5/21/2013 6:26 PM

CQWP

Hey Miles, I just did a test with SP 2010 and a CQWP and it worked for me. Make sure you are using a Web Part Page and that the jQuery library is getting loaded properly. The easiest way to see if jQuery is getting loaded properly is to put an alert in the .read function as follows:

jQuery(document).ready(function($) {
         //Put the Web Part Title for all the Web Parts you wish
         //to put into the tabbed view into the array below.
         alert("jQuery is working");
        HillbillyTabs(["Speakers","Web Part Title 2"]);
    });

if you get the alert, then jQuery is loaded.

If it's still not working, let me know what else may be different from my test.

Good luck!
mark
EMS\markrackleyNo presence information on 5/21/2013 7:49 PM

Hey Thanks It Showed Tab In Edit Form also But Not Getting Content

Hi As you Said i have done its displaying tabs in Editform also but not showing Content as you described to CQWP i have kept a alert in Read Fn alert is Coming . and one Strange Thing is Content is Showing In Firefox ,Chrome....

and I have noticed That when Document Mode is Set to IE8 in IE its working when Document Mode is IE7 its not working any Ideas? 
 on 5/22/2013 2:51 AM
1 - 10Next

SharePoint Architect, Developer, Blogger, Speaker, Author, and general pain in the butt.
 
Thoughts, views, and opinions expressed in this blog are solely my own.
 
Remember, the Impossible just takes longer.
​​​​
 

 Blogs you should be reading