Links List with Favicons and Under the QuickLaunch

Applies To: SharePoint

SharePoint has a handy list called Links that makes putting together a list of links with a display name pretty simple. Since it’s a normal list you can use views or even XSLT to make it look nice wherever you display it on the page. By default, here’s what a small links list looks like using the Summary View:

It’s not too bad, especially for a simple team site. But with just a little extra work you can have that same list of links display with their favicons and you can move them to some relatively unused real estate – under the QuickLaunch, and on every page in your site.

I’m combining these techniques because that was what I did. Fortunately, you can use the bulk of my tips to get nearly any web part to show up below the QuickLaunch. You can also just use the Favicon information to make your link display snazzy. Also, although I’m demonstrating all of this in SharePoint 2010, you should be able to do everything in SharePoint 2007 as well.

Displaying a Web Part Beneath the QuickLaunch

In order to place a Web Part below the QuickLaunch, you’re going to have to edit the Master Page. There are a couple of options. You can add a Web Part Zone and then customize this area on a page by page basis, or you can do what I’m going to demonstrate: add a specific web part to every page on your site.

Open your site in SharePoint Designer (Site Actions -> Edit in SharePoint Designer). Choose Master Pages in the Navigation pane and right-click on v4.master and choose Copy then right-click and choose Paste. Right-click on the new Master Page, v4_copy(1).master, and choose Rename. Once you’ve renamed it, right-click on it and select Edit File in Advanced Mode:

Depending on your site’s settings, you might have to check it out. If so, make sure you check it back in when done and verify you’ve published a major version so that those without full control can see your changes.

We’re going to place our web part right below the quicklaunch. So scroll down to approximately line 594 (in Code view) where you should see two closing divs shortly below the PlaceHolderQuickLaunchBottomV4 UIVersionedContent control. If you want your web part to be included in the leftpanel then press enter after the closing div in line 592, if you want it placed below the box press enter after the closing div in line 594:

Type <br /> and press enter again. Press Save. You’ll get a warning about customizing the page, go ahead and click Yes.

Now switch to the Insert ribbon and select Web Part > Content Query:

Switch to the Design view and right-click on your new web part and choose Web Part Properties. In the dialog window expand the Query section. Choose Show items from the following list under Source and click Browse… and choose your Links list.

Expand the Presentation section. Set Sort items by to <None> (This is to ensure the custom ordering allowed by Links lists is used). Uncheck the Limit the number of items to display checkbox.

In the Fields to display section enter Url [Custom Columns]; for the Link and remove the Title entry:

Choose any other display options you want (I expanded Apperance and chose Chrome Type: None). Press OK to close the dialog. Save the master page. In the navigation pane on the left, right-click on your master page and choose Set as Default Master Page:

Now when you refresh your site you should see the changes (Be sure to publish a major version and/or check in the file if required to ensure everyone can see it):

Adding Favicons to the Links

The above screenshot is pretty cool. Unfortunately, instead of using the display text, it just uses the link. It also doesn’t open the links in a new window. We’ll fix these issues and add a favicon using some simple XSL.

I found the basic XSL to fix the Links display on Marc D Anderson’s blog who apparently got it from this Microsoft forum thread. We’re going to straight up copy that XSL and tweak it just a little to add our favicons. Here’s our customized XSL:

<xsl:template name="LinkList" match="Row[@Style='LinkList']" mode="itemstyle">
	<xsl:variable name="SafeLinkUrl">
		<xsl:call-template name="OuterTemplate.GetSafeLink">
			<xsl:with-param name="UrlColumnName" select="@URL"/>
		</xsl:call-template>
	</xsl:variable>
	<xsl:variable name="DisplayTitle">
		<xsl:call-template name="OuterTemplate.GetTitle">
			<xsl:with-param name="Title" select="@URL"/>
			<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
		</xsl:call-template>
	</xsl:variable>
	<xsl:variable name="TheLink">
		<xsl:value-of select="substring-before($DisplayTitle,',')"/>
	</xsl:variable>
	<div id="linkitem" class="item link-item" style="padding-left:10px;">
		<xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
		<img src="http://www.google.com/s2/favicons?domain_url={$TheLink}" align="middle" style="padding-right:2px;" />
		<a href="{$TheLink}" target="_blank" title="This link opens in a new window">
			<xsl:value-of select="substring-after($DisplayTitle,',')"/>
		</a>
	</div>
</xsl:template>

The main changes I made were the additional padding added to the div in line 16 to get everything to line up with the QuickLaunch links and the img element in line 18.

The img element uses a special link from Google (found on the Coding Clues blog) concatenated with our link’s URL. This link allows us to dynamically retrieve the favicons without having to store them within SharePoint or maintain them as links get added or changed.

So where do we put the above XSL? In your site collection’s Style Library there is a folder called XSL Style Sheets. Open the ItemStyle.xsl file and scroll all the way to the bottom. Just before the final node, </xsl:stylesheet>, paste the above XSL. Since this is just a named template, this won’t affect anything else within your site collection. Upload the changed ItemStyle to the XSL Style Sheets folder and make sure to Publish a major version of the file so everyone can see it:

Now we need to tell our Links Content Query web part to use this item style. So, back in SharePoint Designer, right-click on your Content Query web part and choose Properties. Scroll down to ItemStyle and change it from Default to LinkList:

Save the master page and refresh your site and you should see something similar to this:

Isn’t that pretty!? Now everyone loves you!

Remove Drop Off Libraries from Every Site

Applies To: SharePoint 2010

The other day I came across a problem with some missing features on a few of our sites. Some quick searching told me I needed to enable all my sites to use the SharePoint Server Enterprise Features. This is a good thing to do, especially if you’ve just upgraded from 2007 to 2010 or you were using Foundation or Standard Server.

So, I went to Central Administration and clicked on Upgrade and Migration and chose Enable Features on Existing Sites. I was presented with this screen:

So, I checked the box and pressed OK. It took a few hours, but then everything was good to go! Almost…

Turns out I had people asking me what this new Drop Off Library link was on their sites. A quick check showed that EVERY SITE in EVERY SITE COLLECTION in EVERY WEB APPLICATION now had the Content Organizer feature enabled and a Drop Off Library added.

So, I go to Manage Site Features I deactivate the Content Organizer and go to delete the Drop Off Library. No delete option in Library settings. Turns out you need to use something like SharePoint Manager or Powershell to allow the library to be deleted before that link will show up. Regardless, we have hundreds of sites and my sites – All of which now have an unremovable library and unnecessary feature activated.

So, time for some Powershell! I wrote a script (below) that will cycle through all the sites in all the site collections for a given Web Application and disable the DocumentRouting feature (Content Organizer) and delete the Drop Off Library. I was inspired by this forum thread and this blog post.

Additionally, I was also faced with the complication that I had actually activated this feature previously for a few sites and wanted to make sure they weren’t stripped along with everybody else. So I added an ExclusionURLs parameter. I’ll explain more about that and how the rest of the script works in a minute.

The Script

Param(
	[parameter(position=0)]
	[String]
		$WebApplicationURL,
    [parameter(position=1)]
    [Boolean]
        $AnalysisOnly = $true,
	[parameter(position=2)]
	[String[]]
		$ExclusionURLs
)

#Display Exclusion URL information
if($ExclusionURLs -and $ExclusionURLs.Count -gt 0) {
    Write-Host "Excluded URLs:" -foregroundcolor green
    $ExclusionURLs | ForEach-Object {
        Write-Host "     $_" -foregroundcolor green
    }
} else {
    Write-Host "No URL Exclusions" -foreground cyan
}

#Display Feature Information
$feature = Get-SPFeature “DocumentRouting”
Write-Host “Feature ID for Content Organizer is called $($feature.DisplayName)" -foregroundcolor cyan

if($AnalysisOnly) {
    Write-Host "ANALYSIS ONLY" -foregroundcolor red
}

#Go Through Every Site
Get-SPWebApplication $WebApplicationURL | Get-SPSite -Limit ALL | Get-SPWeb -Limit ALL | ForEach-Object {

    #Check for Exclusion
    if(!($ExclusionURLs -contains $_.URL)) {
        Write-Host "$_ | $($_.URL)" -foregroundcolor DarkCyan

        #Disable Feature if found
        if ($_.Features[$feature.ID]) {
            Write-Host “  Feature $($feature.DisplayName) Found" -foreground green
            if(!$AnalysisOnly){
                Disable-SPFeature $feature -Url $_.Url -Force -Confirm:$false
                Write-Host “  Feature $($feature.DisplayName) Disabled” -foreground magenta
            }
        } else {
            Write-Host "  Feature $($feature.DisplayName) NOT Found" -foreground yellow
        }

        #Delete Drop Off Library if found
        $list = $_.Lists["DROP OFF LIBRARY"]
        if ($list) {
            Write-Host “  List $list Found” -foregroundcolor green
            if(!$AnalysisOnly){
                $list.AllowDeletion = $true;
                $list.Update()
                $list.Delete()
                Write-Host “  List $list Deleted” -foreground magenta
            }
        } else {
            Write-Host “  Drop Off Library NOT found” -foregroundcolor yellow
        }
    }

}
Write-Host " "
Write-Host "All Done!" -foregroundcolor yellow

You can copy the above script, save it in a text file with a ps1 extension and run it from the console. Assuming you’ve named the file RemoveDropOffLibraries.ps1 you can run it in a couple of different ways:

Analysis Only:

Since I’m the cautious type, I want to know which sites are going to be affected before I actually pull the trigger. So running it with just the Web Application URL will provide you with a list of all sites. Additionally, you’ll be told if a given site has the DocumentRouting feature enabled and if a Drop Off Library was found.

Perform Actions:

If you’re comfortable with the results above, just pass the Web Application URL and $false for the AnalysisOnly parameter. This will do the same list of sites and indicate if the DocumentRouting feature is enabled and if a Drop Off Library was found. Each time the feature is found activated, it gets disabled and you’ll see a message. Additionally, each time a Drop Off Library is found, it gets deleted and you’ll see a message.

Analysis Only with Exclusions:

Exclusions allow you to pass site URLs in a comma separated list. Doing the above command ensures your exclusions are working. Just specify the Web Application URL, $true for AnalysisOnly and then 1 or more exclusion URLs separated only by a comma.

Perform Actions with Exclusions:

This uses the same rules for exclusions as above, but instead of just analyzing, it actually does the work.

Quick Tip:

If you have a lot of sites and want to be able to see the output easily, use the start-transcript and stop-transcript cmdlets like so:

start-transcript -path SomeFile.rtf
...Commands and Output...
stop-transcript

Just replace line 2 with one of the command examples from above.

 

Surely no one else will ever end up in this situation, but just in case – there ya go!

InfoPath List Form Enhanced Text Showing All Grey and Stuff

Applies To: SharePoint 2010, InfoPath 2010

As mentioned in my previous post, you can replace the standard list item forms with InfoPath browser based forms (SharePoint 2010 Server Enterprise only). This is a great feature but there are some gotchas that can be hard to find answers to; mostly because these types of forms have different limitations and options than other InfoPath forms.

I was using this feature and had a form view for New, Edit & Display and everything was mostly working. However, my display view was annoying the crap out of me. My list has a couple of Multiple lines of text columns that allow Enhanced rich text (Rich text with pictures, tables, and hyperlinks). Although these displayed just fine on a standard List Item Display Form, they were Grayed out on my InfoPath List Item Display Form.

This means that although it would show formatting such as bold or underline, any text colors you picked were totally overridden with that obnoxious gray:

Turns out I had set the view to Read-only (This is the Display view so that seemed like an important step to me). In my desperation I opened up the View Properties and unchecked the Read-only box, hit OK and re-published the form.

When I opened the List Item Display view everything looked perfect. Apparently InfoPath and/or SharePoint is smart enough to know to make everything uneditable when displaying a list item:

InfoPath List Form New Item is Read Only

Applies To: SharePoint 2010, InfoPath 2010

Many of you are probably aware that you can replace the standard list item forms with InfoPath browser based forms (SharePoint 2010 Server Enterprise only), and if you weren’t, you are now. It’s as simple as hitting the Customize Form button on the List tab of the List Tools ribbon:

By default the same form is used for all three views (New, Edit, & Display). You can create new views in InfoPath (Page Design tab -> New View) and then back in SharePoint use the Form Web Parts dropdown shown above to customize the InfoPath Form Web Part to show the view you want. There are other guides out there to getting this done that go into more detail, but that’s the gist of it.

I ran into an interesting problem the other day when using this feature. I had a form view for New, Edit & Display and everything was working great. Then I realized that I had some optional fields that I didn’t want to show on the display form if they were blank.

So I wrapped those up in a section and slapped a formatting rule to “Hide this control”:

Boom! I published the form and everything displayed as expected. I did a bunch of other stuff and then went back to add another item to the list. Suddenly the form view I was using for the New List Item was completely Read-only. Obviously, that’s a problem.

I opened the form back up in InfoPath and made sure the View Properties didn’t have the Read-only checkbox checked – Nope. I cried a little but then through the blur of my tears I noticed that every field on every view that wasn’t in one of my auto hide sections had a little blue info icon. Hovering over the icon showed FieldName (Control bound to missing field or group). What a heck?

Meanwhile the Edit form is still working great. So I right-clicked on the fields choose Change Binding and verified they were all hooked up correctly. Some searching brought me to this TechNet thread. The answer is in there but it wasn’t super obvious to me.

Basically, by adding the sections I had caused all the other fields on all the views to be outside the SharePointListItems_RW section and this breaks their binding. So how do you fix it? It’s actually pretty simple.

Right-click on any of your Optional Sections and choose Section Properties from the context menu. In the Default settings section of the Data tab is a radio button. Switch it from Do not include the section in the form by default to Include the section in the form by default. Click OK.

Suddenly all the little blue info icons go away and every Optional Section is now called Section. Re-Publish your form and you’ll find the auto-hiding still works perfectly and your New Item form is no longer Read-only. See? It can’t rain all the time sunshine!

Hide “All Site Content” Link Based on Permission

Applies To: SharePoint

By default in SharePoint 2010 nearly every visitor to your site automatically gets an “All Site Content” link added to their quick launch. In addition, there’s a “View All Site Content” option in the Site Actions menu. Here’s a default team site as seen by a user with only Read permission:

For team sites and basic work areas this is a great idea. However, there are several cases where it would be better if this wasn’t shown to the average user – for instance, a Business Intelligence Center. A Business Intelligence Center site is where you’re probably hosting PerformancePoint content and/or reports, etc. Anyone using your dashboards must have read permission to all the content and datasources. But generally you don’t want general users browsing this content. It’s better to provide good navigation either through the quicklaunch or a nice home page. However, you want your designers to still have this link.

Fortunately, Microsoft built the quicklaunch link with a ClusteredSPLinkButton and the Site Actions link with a MenuItemTemplate both of which have the PermissionMode and PermissionsString properties. These controls allow you to perform simple permission trimming.

SPSecurityTrimmedControl Permission Trimming

The controls both inherit from SPSecurityTrimmedControl which is where the permission trimming properties and methods come from.

The first property, PermissionsString, defines the permission(s) a user must have in order to view the control. You can find a list of permissions here. By default both of the All Site Content link controls use the ViewFormPages permission (Basically, anyone who can get to the site).

You can use multiple permissions in your PermissionsString by separating them with a comma. How those are used is determined by the PermissionMode property which can have two values: Any or All. When set to “Any” the control will show if a user has at least one of the permissions in your PermissionString. When set to “All” the control will only show if a user has every permission listed in your PermissionString.

We wanted the All Site Content links to only show for users with Full Control over a site. So our PermissionsString needs to be ManageWeb, and since we’re only using one permission our PermissionMode can be either Any or All or even not included.

Hiding the Quicklaunch Link

To change the permission trimming attributes for our controls, we have to edit the MasterPage. If you’re developing a custom branding solution then this should be easy enough to do directly in Visual Studio. If you’re just customizing on the fly, then you’ll use SharePoint Designer (Choose Edit in SharePoint Designer from the Site Actions menu).

In the default master page (v4.master) the Quicklaunch All Site Content link can be found around line 573 and is included in the PlaceHolderQuickLaunchBottomV4 UIVersionedContent control. Here’s what it looks like by default:

<SharePoint:ClusteredSPLinkButton
	id="idNavLinkViewAllV4"
	runat="server"
	PermissionsString="ViewFormPages"
	NavigateUrl="~site/_layouts/viewlsts.aspx"
	ImageClass="s4-specialNavIcon"
	ImageUrl="/_layouts/images/fgimg.png"
	ImageWidth=16
	ImageHeight=16
	OffsetX=0
	OffsetY=0
	Text="<%$Resources:wss,quiklnch_allcontent_short%>"
	accesskey="<%$Resources:wss,quiklnch_allcontent_AK%>"/>

So all we have to do is change line 576 to read PermissionsString=”ManageWeb” and save.

Hiding the Site Actions Link

The Site Actions menu is just as easy to edit. The View All Site Content link can be found around line 137 inside the SiteActions FeatureMenuTemplate control. Here’s what it looks like by default:

<SharePoint:MenuItemTemplate runat="server" id="MenuItem_ViewAllSiteContents"
	Text="<%$Resources:wss,quiklnch_allcontent%>"
	Description="<%$Resources:wss,siteactions_allcontentdescription%>"
	ImageUrl="/_layouts/images/allcontent32.png"
	MenuGroupId="300"
	Sequence="302"
	UseShortId="true"
	ClientOnClickNavigateUrl="~site/_layouts/viewlsts.aspx"
	PermissionsString="ViewFormPages"
	PermissionMode="Any" />

Again, just change line 145 to PermissionsString=”ManageWeb” and save.

That’s it! Here’s what the same Team Site now looks like to a user with Read permission: