Tag Archives: asp.net

SharePoint Designer Modifies HTML On Save

The “Designer” in SharePoint Designer is used a little too liberally I think, but regardless here are two issues that SharePoint Designer does to your markup when saving the file. As far as I know this issue happens in both the 2007 and 2010 versions. Also, despite looking through all the program’s options, I can’t find one that causes this behavior to turn it off.

Designer Removes Closing HTML Tags

The first is that it removes closing HTML tags. This happens when you use the shorthand to close a SharePoint control. Here is what it looks like when this issue comes up.

<p>
<SharePointWebControls:fieldvalue id="BoxFourContent" FieldName="BoxFourContent" 
     runat="server"/>
</p>

When saving the file (in this case a page layout), SharePoint Designer removes the closing paragraph tag. To change this instead of using the shorthand to self-close the SharePoint control use the longer version.

<p>
<SharePointWebControls:fieldvalue id="BoxFourContent" FieldName="BoxFourContent" 
     runat="server"></SharePointWebControls:fieldvalue>
</p>

Designer Adds a Non-Breaking Space Character

The second issue is SharePoint Designer adding a non-breaking space character when saving. Here is the markup that causes the issue.

<h2>
<SharePointWebControls:fieldvalue id="PageTitle" FieldName="Title" runat="server"/>
</h2>

In this case simply wrap the control in a span, and the issue goes away. Notice I am using a self-closing tag, yet for some reason in this instance (in the very same document) it doesn’t remove the closing HTML tag. Perplexing.

<h2><span>
<SharePointWebControls:fieldvalue id="PageTitle" FieldName="Title" runat="server"/>
</span></h2>

The first rule of a good web design tool: don’t mess with my markup.

Site Title Above Quick Launch

Adding the Top-Level Site Title as a Navigational Aid

I’ve had an interesting requirement show up in the last few projects. All of them were public-facing, and they wanted to have a navigational aid above the quick launch to show the top-level site title. In other words, if the site is contained within a top-level site called “What We Know,” then above the quick launch that text will show up to aid give the user an additional aid in understanding what section of the site they are in.

Site Title Above Quick Launch

I had no idea how to accomplish this so I reached out to my talented co-worker at Portal Solutions Carlos Fernandez. Carlos was able to give me an interesting and reusable solution I’d like to share. I take no credit for this code. I modified a part of the jQuery to pull in the anchor, but the approach and everything else was his work.

Including a Custom AspMenu

The first thing that has to happen is including another instance of the ASP.NET AspMenu control, but it uses a custom sitemap provider with custom attributes. Notice that it has a custom SiteMapProvider, and it has a StartingNodeOffset value. I also use the SharePoint:ProjectProperty control to give the title and URL of the root site; the reason for this is that the AspMenu renders nothing in the root site since it’s using an offset.

<span id="siteTitleValue" style="display:none;">
 <PublishingNavigation:PortalSiteMapDataSource
	ID="SiteTitleDS"
	runat="server"
	EnableViewState="false"
	SiteMapProvider="CombinedNavSiteMapProvider"
	StartFromCurrentNode="false"
	StartingNodeOffset="1"
	ShowStartingNode="true"
	TrimNonCurrentTypes="Heading">
  </PublishingNavigation:PortalSiteMapDataSource>
  <SharePoint:AspMenu
	ID="SiteTitleNav"
	runat="server"
	EnableViewState="false"
	DataSourceID="SiteTitleDS"
	UseSeparateCSS="false"
	UseSimpleRendering="true"
	Orientation="Vertical"
	StaticDisplayLevels="1"
	MaximumDynamicDisplayLevels="0"
        CssClass=""
	SkipLinkText="<%$Resources:cms,masterpages_skiplinktext%>">
  </SharePoint:AspMenu>
</span>
<span id="rootSiteTitle" style="display: none">
	<SharePoint:ProjectProperty Property="Title" runat="server" />
</span>
<span id="rootSiteUrl" style="display: none">
	<SharePoint:ProjectProperty Property="Url" runat="server" />
</span>

Using jQuery to Surface the Title

Using jQuery we can pull the top-level site title that the subsite is contained in and display it in custom HTML without all the HTML from the AspMenu. First is the HTML you used to embed it in the desired location. This uses a heading one which if you use that element elsewhere you might want to downgrade the header (as a semantic best practice you keep a single h1).

<h1 class="siteTitleDisplay s4-notdlg"></h1>

Here is one example where you don’t need the title to be an anchor. Notice how the PrepareDisplayValue function deals with the root site, because as mentioned above the menu doesn’t render anything for the root site.

jQuery(document).ready(function ($) {
var titleText = $.trim( $("#siteTitleValue .menu-item-text").text() );
$(".siteTitleDisplay").html(PrepareDisplayValue(titleText));
function PrepareDisplayValue(titleText) {
	if (titleText.length == 0) {
		var titleText = $("#rootSiteTitle").text();
			return titleText;
		}
	else {
		return titleText;
	}
}
});

If you want to include the anchor to the top-level site you can use the following jQuery snippet.

jQuery(document).ready(function ($) {
var titleText = $.trim( $("#siteTitleValue .menu-item-text").text() );
var titleURL = $("#siteTitleValue a.menu-item").attr("href");
$(".siteTitleDisplay").append("<a href='" + PrepareUrlValue(titleURL) + "'>" + PrepareDisplayValue(titleText) + "</a>");
function PrepareDisplayValue(titleText) {
	if (titleText.length == 0) {
		var titleText = $("#rootSiteTitle").text();
		return titleText;
	}
	else {
		return titleText;
	}
}
function PrepareUrlValue(titleURL) {
	 if (titleURL == undefined) {
		var titleURL= $("#rootSiteUrl").text();
		return titleURL;
	}
	else {
		return titleURL;
	}
}
});

Hiding the SharePoint Ribbon from Anonymous Users

Working on a couple of public-facing 2010 sites hiding the ribbon has become an issue in each of them (I’ve noticed several public-facing 2010 sites that don’t hide the ribbon, but that’s not an option if you want a clean brand). Searching for the solutions turned up a couple of solutions, but neither solution in itself turned out to be the best option.

Searching I found this Technet forum post. In that solution it is a complete CSS solution using a control detecting anonymous and logged-in users. This solution works just fine, but I wasn’t happy with simply hiding the ribbon. If I didn’t need the ribbon why waste all that load time and HTTP requests to load it only to hide it?

This led me to look for another solution, and I found another one that used security trimmed controls to not load the ribbon if not logged in. This was great! I was excited until I logged out to test, and I then realized the vertical scrollbar was hidden. The reason for this is because SharePoint 2010 hides the vertical scrollbar and adds in a custom scrollbar to stick the ribbon to the top. When you hide the ribbon the scrollbar doesn’t show because SharePoint uses overflow: hidden; in CSS for the body so it can handle the scrollbar.

The Hybrid Approach

This led to take both of them to construct the best solution. I used the security trimmed control to hide the ribbon, and then I used the control from the forum post and modified the CSS to handle the scrollbar. Here are the steps combining both of the solutions and including my addition.

1. Add the following before the start of the ribbon.

<Sharepoint:SPSecurityTrimmedControl runat="server" Permissions="AddDelPrivateWebParts">

The ribbon starts with the following HTML.

<div id="s4-ribbonrow">

2. Then close the security trimmed control at the end of the ribbon. It should look like the following.

<Triggers>
 <asp:PostBackTrigger ControlID="WebPartAdder" />
 </Triggers>
 </asp:UpdatePanel>
 </div>
</div>
</SharePoint:SPSecurityTrimmedControl>

3. Add the following outside of the security trimmed control (I put it before, but it doesn’t matter). You’ll notice now the body is set to scroll on overflow, and since it’s on the page it will trump the SharePoint style due to the cascade.

<asp:LoginView id="LoginView" runat="server">
 <AnonymousTemplate>
 <style type="text/css">
 body { overflow-y: scroll !important; overflow-x: hidden; }
 body #s4-workspace { overflow-x: hidden; overflow-y: auto !important; }
 </style>
 <!--[if lte IE 7]>
 <style type="text/css">
 html { overflow: auto !important; overflow-x: hidden; }
 body { overflow: auto !important; }
 </style>
 <![endif]-->
 </AnonymousTemplate>
</asp:LoginView>

Note: This supports IE 6 kind of. It will give a vertical scrollbar, but another one is also added. If I’m forced to find another solution I’ll post it, but I’m sick of IE 6.

This also fixes scrolling on iOS devices as well which don’t take kindly to the way SharePoint 2010 does scrolling by default. Hiding the ribbon alleviates the problem and returns one-finger scrolling.

UPDATE: I realized while implementing this for a client that the permissions level to keep the ribbon from loading was too high. I have since changed the permission level from ManageLists to AddDelPrivateWebParts (a role on the OTB contribute group, because why would you have read only users authenticate?). If you use a custom role be sure to match the lowest authenticated user to a role in this list on MSDN.