Html in SharePoint 2010 WebPart Title

1

Category : SharePoint 2010

I received an interesting SharePoint design today where the WebPart titles had two colors. Ex: the place for News and Announcements

I wasn’t really sure how to accomplish this since SharePoint renders the WebPart titles as simple h3′s with spans in them. At first I thought I’d just type html into the title area. So, I decided to put this in my title: the place for <span> News and Announcements </span>. Then I used css to do my colors: I made the .ms-WPTitle light grey and the .ms-WPTitle span green. But, of course it wasn’t that easy. SharePoint actually wrote out the word “span” instead of rendering it as html: Ex: the place for <span>News and Announcements</span>

At this point I thought I was stuck. I figured I was going to have to add content editor WebParts on top of all my other WebParts just to build titles. It was going to be a pain. But, as I was looking at the underlying html that SharePoint produced, I had an idea. It looked like SharePoint was setting to the html to the actual text literal. So, what if I use javascript to re-write the exact same text? Javascript should write it as html, right?

Anyway, without further ado, here is my javascript. I used jquery (because I have it in my masterpage). I am sure it can be done with regular javascirpt, but this was easier for me.


$(function () {
    //Replace webpart header text with html version
    $('.ms-WPTitle span').each(function () {
        $(this).replaceWith($(this).text());
    });
});

With the above javascript referenced in my MasterPage, it renders any html I put into a WebPart header now. I think it is a pretty interesting trick that could be used for all different kinds of designs.

SharePoint provision default WebParts for MySites

Category : SharePoint 2010

SharePoint adds a new site collection for every user when their MySite is created. Recently I had a requirement to add a custom WebPart into a zone on the root page when the MySite gets created. I accomplished this requirement with the following:

  • Feature to create the WebPart
  • Feature Receiver to add the WebPart (this feature receiver ran off of the Feature to create the WebPart)
  • Feature Stapler to activate the Feature to create the WebPart when the site collection is created

The Feature to create the Webpart and Feature Stapler were easy (standard SharePoint development). The Feature Receiver to add the WebPart to a zone on the page is where it got a little tricky and is why I felt a blog is necessary.

Steps

  1. Create a new SharePoint 2010 solution in Visual Studio 2010
  2. Right-click on your project and choose to add a WebPart Feature (you can use a regular webpart or a visual webpart).
    1. For purposes of this blog, we will call this “MySiteWebPartFeature”
    2. Make sure this is a “Site” scoped Feature
  3. Right-click on your project and choose to add an Empty Element for your Feature Stapler
    1. For purposes of this blog, we will call this “MySiteFeatureStapler”
    2. Add a FeatureSiteTemplateAssociation to the MySite templates. Please delete the Id in the example below and replace it with the Id of the feature you created in Step 2
      <FeatureSiteTemplateAssociation Id=”9f8085c2-70cb-4ce1-814b-52e3967e5c3e” TemplateName=”SPSMSITEHOST#0″/>
      <FeatureSiteTemplateAssociation Id=”9f8085c2-70cb-4ce1-814b-52e3967e5c3e” TemplateName=”SPSPERS#0″/>
  4. Right-click on your Features and choose “Add Feature”. This is for your Feature Stapler.
    1. For purposes of this blog, we will call this “MySiteFeatureStapler”
    2. Set the Scope of this Feature to “WebApplication”
    3. Make sure the “MysiteFeatureStapler” element is added as an Item in this feature. Also, go back to the MySiteWebPartFeature and make sure the “MysiteFeatureStapler” element is removed from that one.
  5. Right-click on the MySiteWebPartFeature and choose “Add Event Receiver”
  6. Add the following code in the Event Receiver

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(RunProcess), properties);
}

private void RunProcess(object state)
{
    SPFeatureReceiverProperties properties = (SPFeatureReceiverProperties)state;

    using (SPSite site = (SPSite)properties.Feature.Parent)
    {
        bool provisioned = false;
        while (provisioned == false)
        {
            provisioned = site.RootWeb.Provisioned;
            Thread.Sleep(5000);
        };

        AddWebPart(site.RootWeb.Url);
    }
}

private void AddWebPart(string url)
{

    using (SPSite site = new SPSite(url))
    {
        using (SPWeb web = site.OpenWeb())
        {
            try
            {
                SPLimitedWebPartManager wpm = web.GetLimitedWebPartManager("default.aspx", System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);

                bool webpartexists = false;
                foreach (Microsoft.SharePoint.WebPartPages.WebPart webpart in wpm.WebParts)
                {
                    if (webpart.Title == "My Custom WebPart")
                    {
                        webpartexists = true;
                        break;
                    }
                }

                if (!webpartexists)
                {
                    Treasury_MySites.PrivacyStatement.PrivacyStatement privacyStatementWebPart = new Treasury_MySites.PrivacyStatement.PrivacyStatement();
                    privacyStatementWebPart.ChromeType = System.Web.UI.WebControls.WebParts.PartChromeType.None;
                    privacyStatementWebPart.Title = "My Custom WebPart";
                    wpm.AddWebPart(privacyStatementWebPart, "TopZone", 0);
                }
            }
            catch
            {
                //do nothing
            }
        }
    }
}

In the end, the Feature Stapler needs to be activated at your web application level. When a new site is created within that web application the MySiteWebPartFeature will activate. When that feature activates it will add the WebPart to the webpart gallery (because that’s the standard behavior of a SharePoint WebPart feature). In addition it will run the custom Event Receiver code upon Feature Activation.

The magic of this solution is in the Event Receiver itself. It is using a seperate thread to make sure the root web gets provisioned before adding the WebParts to the zones on the page. Why is this important?

  • If you don’t use a separate thread you could hold up the web from getting provisioned and you will just hang
  • If the web is not provisioned there is no page to add the WebParts to

Is there other ways of doing this? At first I thought the WebProvisioner class would accomplish the same thing. But, that only works on sub-webs, not the root. Other than that, I couldn’t think of another way other than custom master pages or custom site definitions. I’d be glad to hear if anyone else knows another way.

Slides from Microsoft Monthly Public Sector Development Dinner

Category : Presenting, SharePoint 2010

Here are my slides from my Branding Custom Internet Sites using SharePoint 2010 session at the Microsoft Monthly Public Sector Development Dinner. Thank you to everyone that showed up and thank you for such great comments after the presentation.

Branding Custom Internet Sites in SharePoint 2010.pptx

A Better Enhanced SharePoint 2010 Floating Ribbon

38

Category : SharePoint 2010, SharePoint Ribbon, featured

SharePoint 2010 has issues with its scrolling because of the way it implemented the fixed ribbon. Before we look into these issues (and a workaround) let’s first try to understand what SharePoint is doing. Basically, in order to keep the ribbon fixed at the top of the page, SharePoint put’s the scroll bar on the div tag directly below the ribbon (i.e.: s4-workspace) and removes the “normal” scrollbar for webpages (i.e.: the one that is on the body tag). In order to put the scroll bar on the s4-workspace, they set the overflow property of that div tag. But, in order for an overflow property to work, the height and width must be set appropriately. So, SharePoint also runs javascript on the page load to set the height and width appropriately on the s4-workspace div tag.

The issues noted in this blog are particularly bad on Internet facing sites with SharePoint 2010. They are not that big of deal with Intranet sites. So, I’ve found myself using the techniques in this blog on Internet facing sites and not Intranets. These techniques will work for Intranets, but I don’t like to mess too much with a COTS product when I can help it. I can only hope Microsoft fixes this big issue one day.

SP Ribbon Positioning Issues

  1. IPad and mobile browser use: The reason IPads don’t scroll in SharePoint 2010 is because of how they interact with overflow div tags. Scrolling will work on the IPad if you use the “two-finger” technique. But, nobody will know this is a div instead of a main scroll because SharePoint makes this scroll look like the main scroll. Thus, to the normal user, it just looks like scrolling doesn’t work on your webpage.
  2. Anchor tags: Anchor tagging to sections of the page didn’t work. If you have one page www.mywebsite.com?#bottom that links to another page and the section it is linking too is below the scroll area, you get stuck there. It looks really unprofessional when this happens.
  3. Javascript reliance: A core function of a website should not be reliant on javascript (i.e.: the scrollbars).This can produce multiple issues:
    1. Broken javascript: If any other javascript breaks on the page then the entire site won’t scroll anymore. That is one main reason you don’t make a core function of a page rely on javascript. It is hard to control the other javascript on the page and you can get yourself into bad situations over time with these types of techniques.
    2. Slow loading javascript: You have to wait until all the javascript loads on the page before you can begin scrolling. This is really annoying sometimes.

Microsoft has addressed how to disable this ribbon behavior: http://blogs.msdn.com/b/sharepoint/archive/2010/04/06/customizing-ribbon-positioning-in-sharepoint-2010-master-pages.aspx

Microsoft is basically saying, you can turn this on or turn this off. So, for public facing sites, you will probably want to turn this off. However, this means you content editors won’t get the ribbon pinned to the top of the page. This will make editing content in SharePoint very, very hard.

In my opinion, the fixed ribbon positioning system in SharePoint is a really good idea. But, the “unconventional” implementation causes too many issues with scrolling. I think Microsoft could have implemented this better. Specifically, Microsoft could use the “conventional” fixed position style in css instead of this “unconventional” technique of using overflow div tags. Let me be clear: I don’t think overflow div tags are unconventional. I just think it is unconventional to use that as the main scrollbar on a page.

Solution

Turn off the ribbon positioning system that SharePoint provides and build your own one with fixed position css styles. The steps are actually pretty simple:

Steps

  1. Remove the “scroll=no” attribute from the Body tag
    Note: At this point most people would tell you to remove the s4-workspace tag from your html. In fact, that is what the Microsoft blog mentioned earlier. However, that causes side affects. The gantt chart of task views will stop working, IE7 popups will stop working and anything else that relied on the s4-workspace to be there will stop working. Thus, I do not recommend removing the s4-workspace tag from the html of SharePoint. Instead follow these steps:
  2. Add the following javascript in a script block or an attached javascript file:
    
    //set top padding of the workspace to the height of the ribbon
    function setTopPadding() {
       var wrkElem = document.getElementById('s4-workspace');
       var ribHeight = document.getElementById('s4-ribbonrow').offsetHeight;
       if (window.location.search.match("[?&]IsDlg=1")) {
          //margin works better for dialogs b/c of scrollbars
          wrkElem.style.marginTop = ribHeight + 'px';
          wrkElem.style.paddingTop = '0px';
       }
       else {
         //padding works better for the main window
         wrkElem.style.paddingTop = ribHeight + 'px';
       }
    }
    
    // bind top padding reset to ribbon resize event so that the page always lays out correctly.
    ExecuteOrDelayUntilScriptLoaded(function () { SP.UI.Workspace.add_resized(setTopPadding); }, "init.js");
    

    The above script sets a top padding for our workspace element equal to the ribbon height. This is needed because our new ribbon will be css fixed and that is more of a floating technique. Thus, padding is needed so it doesn’t hang over our workspace.

  3. Add the following css:
    
    body, body.v4.master {overflow:visible !important; height: inherit; width: inherit; }
    
    body #s4-workspace {overflow:visible !important; padding-top:44px;}
    
    /*This sets up our Ribbon for a fixed position. */
    body #s4-ribbonrow{ position: fixed;top:0px;z-index:1000;width: 100%;}
    * html #s4-ribbonrow {position:absolute;} 
    
    /* Set the ribbon popups to be fixed position also */
    #s4-ribbonrow .ms-MenuUIPopupBody, #s4-ribbonrow .ms-popoutMenu, .ms-cui-menu[id ^= "Ribbon."], .ms-cui-tooltip {
    position: fixed !important;
    }
    * html #s4-ribbonrow .ms-MenuUIPopupBody, * html #s4-ribbonrow .ms-popoutMenu, * html .ms-cui-menu[id ^= "Ribbon."], * html .ms-cui-tooltip {
    position: absolute !important;
    }
    
    /*Make sure there are no scroll bars on our popup overlays*/
    .ms-dlgOverlay {width: 100% !important }
    

    Note: I used the star hack above for ie6 (ie6 doesn’t recognize fixed positions correctly and absolute must be used instead). I don’t recommend the star hack (it was for blog purposes only). Please use a seperate ie6 file for ie6 specific css.

That’s it! Now you have a fixed css taking care of keeping the Ribbon on top. Why is this better you ask? The SharePoint’s solution uses javascript to create the scroll area. This means javascript is responsible for whether the site functions or not. My solution uses a fixed css property and only uses javascript to fix the height of the ribbon. Even if javascript is turned off, my solution will work. In addition, my page will work for the public view on all browser types (including IPads).

I started off writing this blog using techniques I thought of. However, I ran across two issues that were problematic. One of the issues had to deal with popus/overlays and other issue dealt with the padding at the top after the ribbon was “fixed”. So, like any good developer, I turned to Google. Thus, I have to give credit to 2 blogs that solve the same issues. In fact, both of these blogs seemed to have taken the same approach I did to this problem. Thus, I used techniques from each blog to come to a solution I feel is the best of all worlds.

The first blog that helped in this solution was: http://www.webpoint0.com/blog/fixed-width-layouts-scrollbar-ribbon-sharepoint-2010/. This blog showed me how to set the top padding of the ribbon in the most elegant way. However, the fix for the popups was not the best on this blog.

The second blog that helped in this solution was: http://kyleschaeffer.com/sharepoint/sharepoint-2010-scrolling/. This blog showed me how to deal with the popups and the popup overlays. However, the fix for the top padding of the ribbon was not as elegant as the first blog.

Once again, thank you so much to the blogs above. Their techniques along with the techniques I had already figured out created a great solution to this common problem.

Issues

Of course, with any solution that changes the core way a system works, there is bound to be issues. We’ve worked through the most common issues in the approach above, but I am confident we haven’t figured out all the issues. So, as issues come up I will post them here so people understand the trade-offs (and maybe come up with solutions for me).

Issue #1: Calendar hovers and add new

When you hover over a day in the SharePoint calendar the “add new” link comes up. This isn’t working “exactly” right in our solution. The reason is, if you scroll down on the page and then hover over a calendar item, the “add new” link shows up in the wrong calendar day. It works perfectly fine if you don’t have to scroll down (the issue only happens when you scroll). I debugged through the javascript and I found the problem. The core.js file of SharePoint has a function called MenuHtc_GetElementPosition. This function recursively loops through the elements of the html and gets the elements position with it’s scroll position to get the x and y axis of the element. However, it never takes into account the documents scroll position. This kind of makes sense because Microsoft doesn’t use the documents scroll position because it overflows the s4-workspace to do scrolls normally. However, we overrode that behavior and went back to the normal scrolling behavior of browsers. I hoped Microsoft would have realized that people would want to do this, but this is one of those functions where the SharePoint code is a little short sighted.

Experimental Solution: This solution overrides the MenuHtc_GetElementPosition function by creating a customcore.js file that gets called after the core.js file. I left the method exactly the same except for one small change. I subtracted the document.documentElement.scrollLeft from the x axis and document.documentElement.scrollTop from the y axis. This should account for our scrolling now.

Note: Microsoft should consider putting this change into their function in the core.js in the next service pack. It wouldn’t affect their “normal” technique for ribbon scrolling and it would help people that are building custom internet sites on SharePoint. I can’t think of a reason they wouldn’t add this into the product. So, if anyone from the Microsoft SharePoint product team reads this, please consider adding this in the next service pack.

  1. Create a javascript file called customcore.js and put the following javascript in it:
    
    function MenuHtc_GetElementPosition(element, relativeToElement)
    {
    	var result=new Object();
    	result.x=0;
    	result.y=0;
    	result.width=0;
    	result.height=0;
    	if (element.offsetParent) {
    		var parent=element;
    		while (parent !=null &&
    			parent !=relativeToElement)
    		{
    			result.x+=parent.offsetLeft;
    			result.y+=parent.offsetTop;
    			AdjustScrollPosition(parent, relativeToElement, result);
    			var parentTagName=parent.tagName.toLowerCase();
    			if (parentTagName !="body" &&
    				parentTagName !="html" &&
    				parent.clientTop !=null &&
    				parent.clientLeft !=null &&
    				parent !=element) {
    				result.x+=parent.clientLeft;
    				result.y+=parent.clientTop;
    			}
    			parent=parent.offsetParent;
    		}
    
            //This is the custom code added to account for scrolling
            //when the code has been customized to not use
            //overflows in the s4-workspace
    		result.x -= document.documentElement.scrollLeft;
    		result.y -= document.documentElement.scrollTop;
    	}
    	else if (element.offsetLeft || element.offsetTop) {
    		result.x=element.offsetLeft;
    		result.y=element.offsetTop;
    	}
    	else {
    		if (element.x) {
    			result.x=element.x;
    		}
    		if (element.y) {
    			result.y=element.y;
    		}
    	}
    	if (element.offsetWidth && element.offsetHeight) {
    		result.width=element.offsetWidth;
    		result.height=element.offsetHeight;
    	}
    	else if (element.style && element.style.pixelWidth && element.style.pixelHeight) {
    		result.width=element.style.pixelWidth;
    		result.height=element.style.pixelHeight;
    	}
    	return result;
    }
    

  2. Save the above solution in 14 hive layouts folder under your language – ex: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\1033

    In addition, save the same file as customcore.debug.js and put it in the same place (Note: if you want a minimum file you can minimize the customcore.js and leave this one around for the debug file)

  3. Replace the reference to core.js
    
    <SharePoint:ScriptLink language="javascript" name="core.js" OnDemand="true" runat="server" />
    


    with this:

    
    <SharePoint:ScriptLink language="javascript" name="core.js" Defer="true" runat="server"/>
    <SharePoint:ScriptLink language="javascript" name="customcore.js" Defer="true" runat="server"/>
    

Enhanced SharePoint 2010 Ribbon with JQuery

5

Category : SharePoint 2010, SharePoint Ribbon

Update: I have a different approach to this problem now at: http://www.greggalipeau.com/2011/01/28/a-better-enhanced-sharepoint-2010-floating-ribbon/. I suggest using my new approach rather than this blog as it is much more elegant.

The most innovative (or at least the most visual) enhancement in SharePoint 2010 is the Ribbon structure. The SharePoint 2010 Ribbon shows up for content editors. And, the ribbon stays at the top of the screen no matter how much you scroll down the page. Thus, if you are editing content at the bottom of the page, the Ribbon will stay pinned to the top of your view as you scroll down. SharePoint implemented this system by actually replacing the browser scroll bars with their own scroll bars through javascript. Sounds really cool, huh. Well, the idea is great, but the implementation causes some issues (especially on public facing websites).

Please Note: This issue is mainly for people that are using SharePoint 2010 as a CMS system for public facing sites. Usually the intent of these systems is to keep the ribbon on for content editors, but off for the general public. I am sure techniques used in this article might help in other situations. But, this is the main situation we are trying to solve.

Issues

  1. Section 508 of the American with Disabilities Act: If you are building a website for the U.S. government you have to comply with section 508 of the American with Disabilities Act. One of the rules is that a page functions when javascript is turned off. This is usually the most ignored rule in building accessible websites because the validity of the rule might be outdated (but, I’m not going to get into that discussion right now). So, if you want to follow the letter of the law, this technique violates this rule because the page isn’t functional (i.e.: can’t scroll) with javascript turned off.
  2. IPad use: When we built a public Internet site in SharePoint 2010 we noticed that we couldn’t scroll on an IPad. Since the other SharePoint 2010 sites I’ve built were Intranets, I did not know this was an issue until I built my first public site. To be completely fair: scrolling sometimes worked on the IPad, but it is problematic. If the scrolling didn’t work you can change orientation or resize a little and it will come back. But, to our end users reporting bugs on the site, they think it just doesn’t work.
  3. Anchor tags: Anchor tagging to sections of the page didn’t work. If you have one page www.mywebsite.com?#bottom that links to another page and the section it is linking too is below the scroll area, you get stuck there. It looks really unprofessional when this happens.

Microsoft has addressed how to disable this ribbon behavior: http://blogs.msdn.com/b/sharepoint/archive/2010/04/06/customizing-ribbon-positioning-in-sharepoint-2010-master-pages.aspx

Microsoft is basically saying, you can turn this on or turn this off. So, for public facing sites, you will probably want to turn this off. However, this means you content editors won’t get the ribbon pinned to the top of the page. This will make editing content in SharePoint very, very hard.

Solution

Turn off the ribbon positioning system that SharePoint provides and build your own one with JQuery. The steps are actually pretty simple:

Assumptions

The following steps assume you already know how to do 2 things:

  1. Create and edit custom master pages in SharePoint
  2. Create a reference to the JQuery libraries in your custom master page

Steps

  1. Turn off the ribbon positioning system

    To turn off the ribbon positioning system you need to edit your custom master page with the following:

    1. Delete the scroll=”no” from the body tag
    2. Replace the “id=s4-workspace” with id=”s4-workspace-noscroll”
    3. Delete the following script tag from the master page:<script>
      var _fV4UI = true;
      </script>

    The following steps are optional and are used to override the behavior of SharePoint hiding the title row when in edit mode. Only follow these steps if you wish to override that behavior. It is recommended to override that behavior for this fix as it looks better for the end user.

    1. Find the class s4-ribbonrowhidetitle (in the s4-ribbonrow tag) and remove the class reference
    2. Find the class s4-titlerowhidetitle (in the s4-titlerow tag) and remove the class reference
    3. Find the tag s4-titlerow and change the id to s4-titlerow-nohide
  2. Setup the html for JQuery Ribbons

    1. Add the following right above the s4-ribbonrow:
      
      <div id="scrollingDiv">
      

    2. Add this above the s4-workspace tag (or the s4-workspace-noscroll if you made that change):
      
      </div>
      

  3. Edit the CSS

    
    #scrollingDiv
    {
     position: absolute;
     top:0;
     z-index:1000;
     width: 100%;
    }
    body {overflow: visible !important }
    body.v4master { overflow: visible !important }
    

  4. Create the JQuery

    
     $(document).ready(function() {
      //Replace SharePoint ribbon scrolling with Jquery ribbon scrolling
      var $scrollingDiv = $("#scrollingDiv");
      $(window).scroll(function(){
       $scrollingDiv
        .stop()
        .animate({"marginTop": ($(window).scrollTop()) + "px"}, "fast");
      });
     });
    

  5. Fix the ribbon dropdowns

    Now that the Ribbon can float/scroll with the page, the dropdown boxes in the ribbon don’t work. The reason is, these boxes use a fixed “top” css property that assumes the ribbon is at the top of the page. We need to change that property to use the top of the scroll position instead of the page.

    
    function setTopPos() {
     $('.ms-cui-menu').each(function(){
         var origTop = $(this).data('origTop') || $(this).position().top;
         $(this).data('origTop',origTop );
         newTop = $(window).scrollTop() + origTop;
         $(this).css({  top : newTop  });
     });
    }
    setInterval(setTopPos, 300);
    


    The above code is the best way I could figure out how to deal with the issue. I actually found the idea in this blogged and tweaked it for our purposes: http://www.webpoint0.com/blog/fixed-width-layouts-scrollbar-ribbon-sharepoint-2010/. Using intervals is obviously not the best way to do anything. But, our code never hits the server, so the interval isn’t a horrible thing. I would have liked to catch the event of the dropdown in the ribbon instead of the interval, but I couldn’t figure out the events SharePoint was using to set the dropdown javascript in motion. So, if anyone has a better way to do this, please let me know. It will work now, I just think it can be more elegant.

  6. Fix the Web Part Edit Panel

    Now that the Ribbon floats it covers up the webpart edit panel (this is the panel that shows on the right when you edit the properties of a webpart)

    1. Add the following CSS to your site
      
      .ms-ToolPaneOuter { margin-top:80px;}
      .ms-ToolPaneBody{overflow-y:scroll !important;overflow-x:hidden !important}
      

    2. Add the following to your custom javascript file
      
      $(document).ready(function() {
       $(".ms-ToolPaneBody").css({  height: ($(window).height() - 245) + "px"});
       var $webPartToolPane = $(".ms-ToolPaneOuter");
       $(window).scroll(function(){
           $webPartToolPane
         .stop()
         .animate({"marginTop": ($(window).scrollTop() + 80) + "px"}, "fast"); });
      });
      

Please Note: In the code above (both the css and the js), there is a static number (80). This number is the amount of top margin for the web part edit panel needed to make sure it is in the appropriate place on the page. That number is optimized for the v4 master page. However, if you create a custom master page (which is what you are most likely doing if you are following this walkthrough). Then you might need to tweak that number depending on the amount of margin and height at the top of your page.

That’s it! Now you have JQuery animation taking care of keeping the Ribbon on top. Why is this better you ask? Well, both my solution and SharePoint’s solution use javascript to implement the ribbon. The difference is, SharePoint’s solution uses javascript to create the scroll area. This means javascript is responsible for whether the site functions or not. My solution uses javascript to position the ribbon. Even if javascript is turned off, my solution will work, the ribbon will just not scroll down with the page. This is OK, because functionally the page will still work, it just will be a little harder to edit content (in that rare case a content editor doesn’t have javascript turned on). In addition, my page will work for the public view on all browser types (including IPads).

The last thing to note about this solution is that your ribbon “floats” on the screen. This means it can cutt off the very top of the page when the page initially loads up. We got around this by running some css for logged in users only (i.e.: only for the people that see the ribbon). In that css, which only runs for logged in users, we just put a top margin on the s4-workspace-noscroll div that is as big as the ribbon itselft. This workaround worked perfectly.

Update: I have a different approach to this problem now at: http://www.greggalipeau.com/2011/01/28/a-better-enhanced-sharepoint-2010-floating-ribbon/. I suggest using my new approach rather than this blog as it is much more elegant.

SharePoint 2010 Menu Sticking Issue

1

Category : SharePoint 2010

So, we just launched www.treasury.gov on SharePoint 2010 in the Amazon cloud. During the course of this project we came across some interesting issues with SharePoint 2010 and I want to report our findings. The first issue we had to deal with is what we called the menu sticking issue.

Before describing the issue, let me explain our menu system. The asp.net menus, in SharePoint 2010, have a property called simple rendering. If this property is true, the menu system is list based (i.e.: ul/li). If this property is false, the menu system is table based. Best practices say that this should be true (i.e.: list based). However, our menu was designed with a fixed width and each section of the menu had a different width to match the word in it. So, it is a very rigid menu in terms of styling. Unfortunately, the simple rendering (i.e.: list based) menus in SharePoint do not put a unique id on each list item. So, we couldn’t size the items for our particular design with that type of menu. Thus, we had to go with the table based menu because each section gets assigned a unique id that we can size through css. I’m not sure if there is any correlation between using table vs list based menus and the bug we found, but I thought it is important to point out.

The second thing to note about our menus is that we use the hover property of the SharePoint asp.net menu to turn the background white when the user hovers over it. Thus, the menu looks like this when a user hovers over a particular section of the menu:

Sticking Issue

The “sticking” issue was a bug that was reported that baffled us at first. We were getting reports that the menu was getting stuck in a hover state. In fact, the background was getting stuck on white and the foreground was getting stuck on white too. It looked like the section of the menu didn’t even exist. Here is an example of what the issue looked like:

The biggest problem with the issue is that we had problems reproducing it. It seemed to happen intermiddently. Eventually we found out how to reproduce it. Basically, it only happend if the user moved their mouse over the menu during the page load. For some reason, when the page loaded up, if the users mouse was moving over the menu, this would happen.

Weird, right? So, I had do dig into what SharePoint was doing to create the hover state and it all has to do with javascript. Basically, the menu system builds this javascript in the page (near the bottom):

spBodyOnLoadFunctionNames.push(‘enableFlyoutsAfterDelay’);
Menu_HoverStatic = overrideMenu_HoverStatic;

Those two javascript methods can be found in the dynamic axd script that the SharePoint menu creates and they look like this:

function overrideMenu_HoverStatic(item)
{ULSxSy:;
       if (!flyoutsAllowed)
       {
              setTimeout(delayMenu_HoverStatic(item), 50);
       }
       else
       {
              var node=Menu_HoverRoot(item);
              var data=Menu_GetData(item);
              if (!data) return;
              __disappearAfter=data.disappearAfter;
              Menu_Expand(node, data.horizontalOffset, data.verticalOffset);
       }
}

function enableFlyoutsAfterDelay()
{ULSxSy:;
setTimeout(“flyoutsAllowed=true;”, 25); }

So, to simplify what they are doing, they are basically putting the mouse hover into an endless loop that only works when the attribute “flyoutsAllowed” gets set to true. That attribute gets set to true on a 25 millisecond delay after the page onLoad event happens.

It seems like they are trying to enforce the entire page gets loaded before the hover event takes place. Now, here in lies the issue. They don’t use a similar technique on the unhover. So, technically, the unhover can happen before the hover because of this technique used.

I went through this code a bunch of times and for the life of me I couldn’t figure out “why” they were doing it. It was pretty obvious “what” they are doing. But, I never found a reason “why”. You don’t need to wait for the page to load for hovers to work. One could assume they wanted to ensure all the html was there for the hover. But, this javascript gets ran at the end of the file, so it is a pretty good assumption it will be there. I came to the conclusion that there was no reason for this hover delay and that this is causing our menu “sticking” issue.

Luckily, SharePoint used a javascript override technique to build their function. So, all I had to do was copy their override method, take out the check for flyoutsAllowed, and the issue was fixed. I just put the following code into my custom .js file on my SharePoint site:
function overrideMenu_HoverStatic(item)
{
var node=Menu_HoverRoot(item);
var data=Menu_GetData(item);
if (!data) return;
__disappearAfter=data.disappearAfter;
Menu_Expand(node, data.horizontalOffset, data.verticalOffset);
}

That was it, the menu “sticking” issue was fixed. We tested this in all major browsers (even the dreaded IE6). We found no issues caused by this fix. I’m not sure why this bug hasn’t been reported yet. Maybe it has to do with out specific situation (SharePoint 2010, table based menus, with background changing on hover state). So, if anyone has a similar issue with this situation, mabye this blog will help you out.

SharePoint 2010 customErrors mode

14

Category : SharePoint 2010

When developing SharePoint components we often times get an error screen with this message:

Server Error in ‘/’ Application.
——————————————————————————–
Runtime Error
Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed.
Details: To enable the details of this specific error message to be viewable on the local server machine, please create a <customErrors> tag within a “web.config” configuration file located in the root directory of the current web application. This <customErrors> tag should then have its “mode” attribute set to “RemoteOnly”. To enable the details to be viewable on remote machines, please set “mode” to “Off”.

Server Error in ‘/’ Application.——————————————————————————–
Runtime Error Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed.
Details: To enable the details of this specific error message to be viewable on the local server machine, please create a <customErrors> tag within a “web.config” configuration file located in the root directory of the current web application. This <customErrors> tag should then have its “mode” attribute set to “RemoteOnly”. To enable the details to be viewable on remote machines, please set “mode” to “Off”.

In SharePoint 2007 we would go into IIS, find our virtual directory and change the CallStack from false to true and the customErrors mode from On to Off.  (reference)

However, that doesn’t seem to work for SharePoint 2010. I made those changes and I still got that annoying generic error message. As it turns out, SharePoint 2010 has a second web.config file located:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\web.config

That second web.config file contains the customErrors section that needs to be set to Off.

Central Administration has a second web.config file too if you need to see error descriptions their:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\ADMIN\web.config

This was very frustrating for me to find, so hopefully this helps someone else.

Branding Custom SharePoint 2010 Internet Site Slides

1

Category : Presenting, SharePoint 2010

Here are my slides from my Branding Custom Internet Sites using SharePoint 2010 session at SharePoint Saturday DC Fed. Thank you to everyone that showed up and thank you for such great comments after the presentation.

Branding Custom Internet Sites in SharePoint 2010.pptx

Speaking at SharePoint Saturday DC Federal

3

Category : Presenting, SharePoint 2010

I am speaking this weekend at SharePoint Saturday DC Federal (http://www.sharepointsaturday.org/dcfederal/default.aspx). I would have posted earlier, but I was a late addition this time.

Session Details:

Branding Custom Internet Sites in SharePoint 2010

In this session we will discuss branding techniques to create custom internet sites in SharePoint 2010. While SharePoint 2010 introduces many innovative techniques such as the new ribbon, it also produces challenges for designers when the design is built for the Internet. What do you do with the ribbon for anonymous users? How do you deal with fixed width sites when SharePoint 2010 uses JavaScript to dynamically size? How do we deal with the new theming framework? What 508 rules should we keep in mind while working with SharePoint 2010?
This session will address all those questions as we work with a government website for Treasury that has been branded for the Internet based on a design prior to SharePoint 2010.

Tips and Tricks for setting up a SharePoint 2010 development environment

Category : SharePoint 2010, featured

While SharePoint 2010 is similar to SharePoint 2007, there are many tips and tricks to setting up a proper SharePoint 2010 development environment. Some of these are the same as SharePoint 2007 and some are new to SharePoint 2010. I run all my development environments in a single server farm configuration on VMWare products.

  1. Use a 64-bit Windows Server environment as your virtual machine because SharePoint 2010 only runs on 64 bit. I am using Windows Server 2008 R2 at the time of this blog.
  2. Make sure your host machine has at least 8GB of RAM. SharePoint 2010 is a beast and you need to allocate at least 5GB to the SharePoint virtual machine (but hopefully you can do more than that). Otherwise it might be slow development for you.
  3. Make sure you host machine has a fast disk. 7200 RPM will work, but 10000 RPM or an SSD drive will make things go faster for you.
  4. Configure your SharePoint virtual machine to act more like a desktop operating system. SharePoint runs on a server which can make the environment act differently than a desktop operating system. I use the Windows 2008 Workstation converter from: http://www.win2008workstation.com/win2008/windows-server-2008-workstation-converter. This allows me to:
    1. Remove the Shutdown tracker
    2. Change the machine name
    3. Disable Enhanced IE Security Configuration
    4. Install Desktop Experience
    5. Disable Verbose messages at startup and shutdown
  5. Install SQL Server 2008 SP1 and the cummulative updates. At the time of writing this blog the latest cummulative updates were required to install SharePoint 2010.
  6. Turn the machine into an Active Directory Domain Controller
  7. Create an sp_admin account in my AD and use this account to setup SharePoint
    1. Give this account DBCreator and Security roles in the SQL Server database
    2. Delegate Replicating directory changes control to this user (this is used in lieu of making the user an administrator on the machine)
      1. In AD Users and Computers applet, right-click your domain and choose delgate control
      2. Choose “Create Custom Task to Deletage”
      3. Choose to delegate control of “This folder, existing objects in this folder”
      4. Choose to pick “Replicating Directory Changes”
  8. Setup environment variables to the 14 hive
  9. Setup a menu on the toolbar to the 14 hive so you have easy access to it on your server
  10. Enable developer dashboard on demand: stsadm -o setproperty -pn developer-dashboard -pv OnDemand
  11. Enable Sandbox Solutions to work on a Domain Controller (typically they don’t). Use the following PowerShell script:

$acl = Get-Acl HKLM:\System\CurrentControlSet\Control\ComputerName
$person = [System.Security.Principal.NTAccount]“Users”
$access = [System.Security.AccessControl.RegistryRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]“ContainerInherit,ObjectInherit”
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$type = [System.Security.AccessControl.AccessControlType]::Allow
$rule = New-Object System.Security.AccessControl.RegistryAccessRule($person, $access,$inheritance, $propagation, $type)
$acl.AddAccessRule($rule)
Set-Acl HKLM:\System\CurrentControlSet\Control\ComputerName $acl