Skip Ribbon Commands
Skip to main content
Home
Fewer big words, more pretty pictures.
April 29
SharePoint 2013 / Office 365 Web Parts in a jQuery UI Accordion

My previous post Tabbed Web Parts in SharePoint 2013 / Office 365 walked you through using a script to place SharePoint Web Parts into the jQuery UI tabs. Based upon the response (and since I’d already done most of the work) I thought I ‘d throw together a quick script for putting Web Parts into jQuery UI’s Accordion feature.  Follow the exact same instructions as in the aforementioned Tab blog post but use the scripts in this blog post instead.

image

The script

<!-- 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($) {
         //Put the WebPart Title for all the Web Parts you wish
         //to put into the jQuery UI Accordion into the array below.
        HillbillyAccordian(["Images","Posts","Customers"]);
    });
    
    function HillbillyAccordian(webPartTitles)
    {
        for(index in webPartTitles)
        {
            var title = webPartTitles[index];
            $("#accordian").append('<h3>'+title+'</h3>');
            $("span:contains('"+title+"')").each(function(){
                if ($(this).text() == title){
                    $(this).closest("span").hide().closest("[id^='MSOZoneCell_WebPart']").appendTo($("#accordian"));            
                }
            });
        }
        $("#accordian").accordion({ heightStyle: "content" });
    }


</script>
<div id="accordian"></div>

 

The script with persisted content

<!-- 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($) {
         //Put the WebPart Title for all the Web Parts you wish
         //to put into the jQuery UI Accordion into the array below.
        HillbillyAccordian(["Images","Posts","Customers"]);
        //show persisted content
        ShowActiveContent();

    });
    
    function HillbillyAccordian(webPartTitles)
    {
        for(index in webPartTitles)
        {
            var title = webPartTitles[index];
            $("#accordian").append('<h3 id="heading'+index+'" onclick="SetCookie(this.id);">'+title+'</h3>');
            $("span:contains('"+title+"')").each(function(){
                if ($(this).text() == title){
                    $(this).closest("span").hide().closest("[id^='MSOZoneCell_WebPart']").appendTo($("#accordian"));            
                }
            });
        }
        $("#accordian").accordion({ heightStyle: "content" });
    }

    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 = "ActiveContent="+id+expires+"; path=/";
    }
    
    function ShowActiveContent()
    {
        var name = "ActiveContent";
        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="accordian"></div>

Ta and Da

Enjoy… I think the tabs look better, but hey, to each his own. Please let me know if you’d like to see any other jQuery UI functionality working in SharePoint and I’ll see what I can do to make it happen.

Cheers!

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> 

<script type="text/javascript">
     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.
        HillbillyTabs(["Web Part Title 1","Web Part Title 2"]);
    });

    function HillbillyTabs(webPartTitles)
    {
        for(index in webPartTitles)
        {
            var title = webPartTitles[index];
            $("#HillbillyTabs").append('<li><a href="#Tab'+index+'">'+title+'</a></li>').after('<div id="Tab'+index+'"></div>');
            $("span:contains('"+title+"')").each(function(){
                if ($(this).text() == title){
                    $(this).closest("span").hide().closest("[id^='MSOZoneCell_WebPart']").appendTo($("#Tab" + index));  }
            });
        }
        $("#tabsContainer").tabs();
}
</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($) {
         //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){
                    $(this).closest("span").hide().closest("[id^='MSOZoneCell_WebPart']").appendTo($("#Tab" + index));  }
            });
        }
        $("#tabsContainer").tabs();
    }

    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>

 

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!

April 02
SharePoint For Everyone! Is SharePoint Online Ready??

Okay! So! Finally able to get back to work on my little side project to set my family up with SharePoint.

SharePoint for Everyone! Yes, Even for Your Family!

Wow, did this step in the process take me on a little side adventure! My goal is to show you guys how quickly, easily, and cheaply the average person can get up and going on SharePoint. I see so many potential uses for it and I know when all is said and done at least *I* hope to get some benefit from it. 

Getting the services

Anyway, this past Sunday night I decided to go ahead and purchase all the services I needed and get up and running with SharePoint Online. Again, my goal here was to do it on the cheap.

Outlook.com

First thing I wanted to do was create a free Microsoft email account to use as the contact email address for my SharePoint Online account. This will be the email address that billing statements are sent to, support uses, and all that jazz. Plus, I REALLY like what they’ve done with Outlook.com. If so many people didn’t know my gmail email address I’d switch to Outlook.com for most of my email needs.

SharePoint Online

The next thing I did was purchase the lowest tier of SharePoint Online, the P1 plan for only $3 a month (That’s cheaper than a cup of coffee from Starbucks people!!).  You have other options if you want to spend more money, and some of the reasons for spending more are quite compelling (I’ll detail just some of those later in this post).

image

I should point out that the price is $3 per user per month, however, I’m so cheap that in my first foray into SharePoint Online for my family, we are all going to use the same account. For my initial purposes everyone using the same account will not be an issue. Long term that won’t be feasible and I’ll need to upgrade to add at least one additional license if for no other reason than permissions.  The other drawback to one license is that it limits user specific alerts and the like, but hey, let’s start out simple and build up from there? okay? 

The process for purchasing SharePoint Online is easy to follow, just following the links and steps provided. Get ready to think of a online account name you’ll want to use.  You’ll initially have to create an account that is username@yoursite.onmicrosoft.com and your default urls will be of the structure http://yoursite.sharepoint.com. Which brings us to my final service I purchased that evening. 

Domain Name Registration

This final step is totally optional, but I wanted to get a custom domain name for my SharePoint Online account. Plus I wanted to change my username and the url for my public site. By purchasing a domain name you can configure your SharePoint Online account to use that domain name for user logins and your public site collection.

I purchased my domain name from GoDaddy.com, but there are many options available.

Alright! Purchases complete! Let’s get everything configured!!!

Configuring SharePoint Online to use my custom domain

Now that I have all my services, I wanted to login to my SharePoint online account and configure it to use my custom domain.  So, after logging in to https://login.microsoftonline.com I clicked on “Admin->Office 365” in the top menu.

image

*It is important to note, that the SharePoint Online P1 plan for $3 a months is for SharePoint Online only! Even though you will see the words ‘Office 365’ everywhere, the only part of Office 365 you are getting is the SharePoint part!*

Anyway, back to the blog, after you click on the above “Office 365” link, click on the “Domains” link from the menu on the left side of the screen:

image

Now simply follow the instructions for setting up your custom domain on SharePoint Online. This turned out to be really easy to do, Microsoft has gone to a lot of effort to clearly document this sometimes cumbersome process.  Great job on making the process easy to understand! 

Ta and Da

So, there you have it. You should be all ready to go and start customizing your SharePoint Experience. You will have four SharePoint Site Collections created for you automatically.  When you are ready you may want to delete/re-create some of these, but what you will start out with will look something like:

image

You’ll have one (and only one) public site collection and three private site collections. You can only assign your custom domain to your public site collection. You’ll also have a team site https://yoursite.sharepoint.com, search site, and your my sites. Getting started I’d just worry about that team site and use that as a play site.

So, go ahead, click on your sites… look around… play… edit your pages.. add web parts… don’t be afraid to play around and see what does what. If you screw something up, just come back to the the above SharePoint Admin Center and delete the site collection and re-create it using the “New” menu button.

In my next blog post I’m going to walk you through deleting that Team site and replacing it a site that is more conducive to the tasks I want to do (I’ll give you a hint… It’s a project site. Keeping a family organized is like a big project.)

NOT SO FAST… It’s not all rainbows and unicorns…

So, if you are going to go for the P1 plan because you are cheap like me, PLEASE be warned. You DO get what you pay for when it comes to support.

When I first went through the process of setting up my custom domain I ran into a problem and it quickly turned into a major issue. On the final step to “Rename” the Public Site Collection, I received a system error when I pressed “OK”.  Don’t remember exactly what the error was… it’s SharePoint… errors happen.

image

Anyway, after the initial error I was no longer able to browse to my public site collection. I was getting a fairly generic error saying there was a problem with the site. No biggie.. right? All I had to do was go back to the SharePoint Admin Center by clicking on “Admin->SharePoint” in the top menu. Click the check box next to the public site collection and then click the delete button. Everything was fine so far, then I clicked the “New” button and selected Public Site Collection. Filled out the information on the form and clicked “OK”. And waited… and then…  

*BAM*

Another error. Crap. I’ve been using SharePoint for several years now. I’m used to errors. Let’s take a closer look at the Site Collection. I clicked the checkbox next to the Site Collection url and then click the “Properties” button in the toolbar.. and then….

O365

Ouch, that is not a good error message. “There is no site in the current site subscription matching the HiddenSiteSelection control’s value”.  Basically, the site is hosed.  No worries, I’ll just delete it and recreate it. So, I try to delete the Site Collection and… SAME ERROR…. UGH…  I’m stuck.. I can’t do anything. Can’t delete the site, can’t view the site, can’t access the properties for the site. This is not a user error.. this is a system error. I’m dead in the water. What’s worse I can’t just create another public site collection because you are only allowed one.  What do I do?

The common sense answer is to call support, but for $3 a month you don’t get phone support. Okay, I can live with that. So, after searching and searching for a way to submit a support ticket I finally track down the link (it’s under Admin->Office 365, NOT under Admin->SharePoint).  I submit a service request around 9:30pm explaining my issue and asking support to just delete the site collection. Don’t bother trying to fix it.  I go to bed that night knowing I’ll be able to get back to work on my site tomorrow.

The morning comes, I check on the status of my service request. No response. I don’t even know if it’s been read yet. That’s frustrating. No ETA, no auto-response saying they received my request, no nothing.  Okay, I wait a few more hours. 

Still nothing.. no movement. Wait a second. I *AM* a paying customer. This is not a free service. My public site collection is down and I’m dead in the water. I have no idea what’s going on. No one is communicating with me. So, I express my thoughts on Twitter and try to find help. One of my MVP friends said they had a few contacts and they sent out some messages to try and get help. No response. The office 365 Twitter account asked me to send them my service request number and they would find someone to take charge of my ticket.  I sent the ticket number and… no response. My public site collection has been down for over 20 hours now and ZERO communication has occurred on my SharePoint Online account. None.

This was really getting frustrating. What if I were an IT Director for a large corporation trying out SharePoint Online and considering investing heavily in it? I’d run away screaming at this point. This is wholly unacceptable. A PFE friend of mine jumped in to help me and we tried to access the site with remote PowerShell. The tools wouldn’t even install  on my computer.

Fast forward. 36 hours have passed and I’ve become quite vocal about my frustration that my public facing site collection is down, I have no alternatives, still ZERO response on my SharePoint Online account. I’m basically looking at 99% DOWNTIME at this point.

Finally, a Senior Program Manger from Microsoft steps up and gets someone at support to give me a call and I get a call from a very nice technician who says he’d like to do a screen share with me to try and see what I might be doing wrong. He then explains if he can’t solve the problem they’ll have to escalate the issue. Well, I’m 99.5% sure he can’t do a thing if we screen share and I don’t want to wait for my ticket to be escalated and see how long that takes. So, I tell him that I’d just like to cancel my subscription and create a new one. He kindly forwards me the number to call and I call and cancel my subscription within a matter of minutes.

After my subscription has been canceled I immediately sign up again, go through the exact same steps I went through the first time, and everything worked brilliantly. No errors. All my sites working. I was even able to delete and recreate one of my site collections. So, it appears my initial error was just a fluke.

I hope you are listening Microsoft

So, I want to make sure you understand what you are up against if you purchase the P1 plan in terms of support. It took 36+ hours, an MVP, the Office 365 Twitter account, a PFE, and finally a Senior Microsoft Program Manager for me to finally get a response to my Service Request. Do you have those kinds of contacts in your back pocket? I can’t even imagine what a normal customer would have to go through?!??

MICROSOFT! This whole situation could have been alleviated with a little thing called COMMUNICATION. Even a freaking auto-response to my service request that says “We’ll received your request and will get back to you within a week because you are too cheap to pay for real support.”  SOMETHING… but no communication ever occurred.

Microsoft, you can do better and you have to do better. Would you like me to write you guys the workflow for the auto response?

But we were within our SLA!

I heard this argument from a few people. You know what, I looked for the SLA for my P1 account and I couldn’t find it. I didn’t look TOO hard, but it was not easily located on the site. I have no idea if they were within their SLA or not, and frankly that’s a little beside the point.  I would have been FINE with waiting IF I knew when to expect a result!! A response saying “We’ve received your request. With your P1 plan, we’ll have your issue resolved within a month. Should this not be sufficient, please consider not being so cheap and upgrading your service.” At least I would know!

Come on Microsoft.

On a final note, consider upgrading to an Office 365 Enterprise plan.

Everyone I’ve talked to that has had a support issue and was on an Enterprise Office 365 plan had nothing but rave reviews for the Microsoft support staff. They were able to pick up the phone and get their issues resolved immediately. Plus the E1 plan is only $8 a month. Not too mention you also get full blown Office 365 including Exchange and Lync. You do get a TON more for a few more dollars a month. Consider it.

image

Is SharePoint Online ready for everyone? It’s a mixed bag. I think if you go with an Enterprise plan, I have no problems recommending Office 365 and SharePoint Online. However, if you are cheap like me and want to go with a P plan, be prepared for a huge lack of support should you need it. But hey, if you never need support $3 a month is an AMAZING value.

And Microsoft, please read my earlier blog post: Just Communicate!!!

1 - 3Next

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.
​​​​
SharePoint Technology Conference