What is MSOLayouts_MakeInvisibleIfEmpty()

I was looking through the code of SharePoint’s Blank Web Part page layout, and I kept finding elements called _invisibleIfEmpty. Now, I’d noticed that some page layouts, such as the Splash page layout had borders on their web part zones which were only shown if the zone contained a web part. I was interested in how this might work. People keep asking for web parts with borders, preferrably ones with rounded corners. Continue reading “What is MSOLayouts_MakeInvisibleIfEmpty()”

What is MSOLayouts_MakeInvisibleIfEmpty()

Putting a web part zone below the quick navigation menu

Previously, I’d been asked to put a web part zone below the quick nav for SharePoint pages. As it transpires, you can’t put web part zones on master pages – but there is no reason why you shouldn’t put one in an asp:Content control (indeed, that’s how you have to place them on pages). And I’d noticed this PlaceHolderLeftActions content placeholder. So I figured, why not put my web part zone into that?

To do this, I need to modify the page that I want this zone to appear for. It could be a Page Layout for publishing pages, or just a normal default.aspx on a team site. I’m using a blank site for this. I simply added a Content control, and dropped a web part zone into it:

<asp:Content ContentPlaceHolderId="PlaceHolderLeftActions" runat="server">
<WebPartPages:WebPartZone id="g_5AD648BF053647678E80875B48A60593" runat="server" title="Zone 1">
</WebPartPages:WebPartZone>
</asp:Content>

I saved the changes, and now when I go to edit that page I see:

Great! I can drop in web parts – here I’ve used a summary links web part:

But you may find the styling leaves something to be desired – but you can design that in!

Sure, you could find that you have to do this a lot of times if you want to do this for many pages, but if you’re using the publishing features, you only have to modify each Page Layout once, which is very handy.

Putting a web part zone below the quick navigation menu

How SharePoint Pages are associated with a Master page

So, yesterday’s discussion of the problems with master pages for Publishing and Meeting sites raised a bit of a question with my colleagues. If a site (SPWeb object in the code) has both MasterUrl and CustomMasterUrl properties, how does a page ‘know’ which one to use? Why do publishing pages use the value in CustomMasterUrl, and other pages use MasterUrl?

Well, to find the answer to that, you’ve got to look in the code of the .aspx content page. Here’s the top of one in SharePoint Designer:

Yup, there is a MasterPageFile as per standard ASP.NET. However, the value of this isn’t normal – it’s not the URL itself, but rather a token that gets replaced at runtime.

  • ~masterurl/default.master is resolved to the value of the MasterUrl property (i.e. the ‘System Master Page’ on a publishing site).
  • ~masterurl/custom.master is resolved to the value of the CustomMasterUrl property (i.e. the ‘Site Master Page’ on a publishing site).

If you look in, say, the default.aspx page on a team site, you’ll see that it uses ~masterurl/default.master.

If you look in, say, the default.aspx page on a meeting workspace, youll see that it uses ~masterurl/custom.master.

If you look in publishing pages, though, you have to look at the page layouts (which are the actual .aspx pages being used). These don’t have a have a MasterPageFile defined – what gives? Well, they inherit from the Microsoft.SharePoint.Publishing.PublishingLayoutPage class, which sets the master page file internally during OnPreInit! You can see in Reflector that it’s using CustomMasterUrl though.

How SharePoint Pages are associated with a Master page

Pages in SharePoint IV – Publishing Pages

Publishing pages are specific to MOSS, as they require the publishing features! They’re not in WSS3! A good example of a publishing page is the default.aspx of a Collaboration site – that’s right, although the default page has the same name as for a team site, it is quite different:

Looks pretty much the same though, eh? That’s because it uses the same master page, but we’ll come to that in a bit.

These pages are are stored in a ‘Pages’ library (you can see this highlighted in the URL). They aren’t really like documents though; they’re much more like list items. Basically, these pages are collections of metadata columns. Different pages have different content types, such as the ‘Press Releases’ page type of the Publishing Portal site template. The other pages types that come out of the box are the ‘Article’ and ‘Welcome’ page types of a collaboration site.

These content types have different columns of data. For example, you might have a type of page for ‘Vacancies’, and that might have columns for position, salary, etc.. You might also have a type of page for ‘Products’ which might have columns for part number, cost, stock, etc..

Okay, so I’ve said that these pages are more like collections of metadata – how does this become a web page that you can see and read? Well, each page type has one or more page layouts. Lets have a look at one in SharePoint Designer:

These are kind of like master pages – they define the layout of our metadata columns in an aspx page. In the one shown above there are only 2 metadata columns, which I’ve highlighted – Page Image and Page Content.

Okay, but what about the master page stuff? Well, out page layout the content controls to go into our master page. Confused? It is confusing, so here is a diagram to show this:

Here you can see the page metadata being put into the page layout, which in turn puts content into the master page, which finally generates the output that gets sent to the user.

One advantage of this approach is that you can change between different page layouts for a given publishing page type – for example, you might have ‘Product page with image on left’ and ‘Product page with image on right’ layouts. Changing the page layout does not require editing any of the content.

| Intro | Master Pages | Normal Pages | Publishing Pages | Application Pages | Forms Pages |

Pages in SharePoint IV – Publishing Pages

My Breadcrumbs have "> Pages > default.aspx" in them

I’ve written about this before, but really it was just an addendum to another point I was trying to make. It might be worth bringing out as a post in itself.

ASP.NET navigation controls take data from a navigation provider, and render it into HTML. The breadcrumbs used in SharePoint use the one navigation control, but give it different navigation providers…

… the point relevant to whether or not the “> Pages > default.aspx” is displayed in the breadcrumbs is the SiteMapProvider. The CurrentNavSiteMapProviderNoEncode provider doesn’t seem to include the ‘Pages’ bit of the path – hence it is used by the page layouts. The Default.master’s SPContentMapProvider provides a breadcrumb that includes the ‘Pages’.

So, if your page is using a breadcrumb such as…

<asp:SiteMapPath id="ContentMap" SiteMapProvider="SPContentMapProvider" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional" runat="server"/>

… then your breadcrumb will include the “> Pages > default.aspx”. Note that this is the default content of the breadcrumb in default.master. Thus, if you’re creating a brand new page layout, you’ll probably want to override that content using an ASP.NET Content control something like this…

<asp:Content ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server">

<asp:SiteMapPath ID="siteMapPath" SiteMapProvider="CurrentNavSiteMapProviderNoEncode" RenderCurrentNodeAsLink="false" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional" Runat="server"/>

</asp:Content>

This code defines a content control that overrides the default content for the Title Breadcrumb. It uses the CurrentNavSiteMapProviderNoEncode (nice name!) navigation provider, and so won’t show the “> Pages > default.aspx” bit in the breadcrumb.

So, in short, when you’re creating a new Page Layout, make sure you override the Title Breadcrumb with something that uses the CurrentNavSiteMapProviderNoEncode provider.

My Breadcrumbs have "> Pages > default.aspx" in them

You can do a lot with page layouts…

I’ve been blogging a fair bit lately about Page Layouts – how they affect styles to hide bits of the page, how they are used to replace breadcrumbs and the like – but you can do a heck of a lot with them.

Quite a lot of your default master page is in ContentPlaceHolder controls. Those ContentPlaceHolder controls have default content – but your page layout can define Content controls which place content into those placeholders, overriding them. Of course, you still need to have all of the appropriate controls on a page – just removing the ‘Site Actions’ menu for everyone isn’t a good idea – but you can do a lot.

This sort of came up at the last SharePoint User Group meeting – Colin Byrne was demonstrating Silverlight in SharePoint (which apparently doesn’t work all that well yet, but shows promise). One of the demos he has showed replacing the left navigation with a Silverlight control, but used a neww Master Page do to that. I thought of a demo I’d done recently where I’d done similar – but with a Page Layout. I used this to replace the left navigation menu with a Web Part Zone:

Normal View

Page Extensively Modified by a Page Layout

Edit View

Page Extensively Modified by a Page Layout - Edit View

Believe it or not, this is actually the default master with a particular Page Layout that I made, and the ‘Simple’ theme applied. Actually, there are lots of bits of the page modified by the Page Layout. The ‘Site Actions’ menu and Top Navigation Bar have been moved up, for example. The Left navigation has been replaced by a Web Part Zone, and I’ve dropped a Content Query Web Part in there for a giggle. And the Search box has been moved down the page too.

You could do all of this with a Master Page of course – and in real life, you’d probably want to for most of those modifications. For some things, though, like replacing certain navigation controls (which is what some of the out-of-box page layouts do with title breadcrumbs) then I think that a page layout might be exactly what you want – so that you can have different forms of navigation for different pages using the same Master Page.

Anyway, I was surprised by how easy it was to do this. Given that the Master Page defines default content, much of what I did was just copy that default content into the Content control for the location that I wanted to put the control into – and voila!

You can do a lot with page layouts…

Modify the RichHTMLField control on your page layouts

When building an intranet, it’s important to try to get consistent styling and formatting, especially if you want to be able to update this later. How do you do this?

To create Pages in SharePoint, you have two options really:

  • Create by hand though the site’s ‘Create Page’ function. Fill in and format your text using the Content Editor Control
  • Create the content in Word, InfoPath, etc., and convert to a Web page using the Document Conversion service.

I’ve been having a bit of a look at this:

Creating Pages through the Web interface

In the SharePoint site, create a new page. Depending on the layout, often they have a RichHTMLField control. In Edit mode, this displays a content editor:

Normal Content Editor Control

and when published, it just displays that content.

However, this control has a lot of options. Editors can adjust text fonts, sizes, colours, boldness – they can even get into the HTML and edit that! I quite like this, but it’s hardly conducive to having a consistent style. What would be good would be to have a number of pre-defined styles, and lock out the other control options.

First, let’s look at removing those option buttons. It turns out that the RichHTMLField control has a number of properties you can set to disable these. This works nicely:

<PublishingWebControls:RichHtmlField id="content" FieldName="PublishingPageContent" runat="server" DisableBasicFormattingButtons="True" AllowTables="False" AllowHtmlSourceEditing="False" AllowLists="False" />

Results in:

Modified Content Editor Control

What I’ve not yet been able to figure out is how to disable the ‘standard html format’ menu thing (the paragraph sign ΒΆ ). I know that it’s for formatting the whole of a paragraph – but we have some problems with that, as we’ll see later. Anyway, now we’ve got those buttons disabled, user’s are MUCH more restricted in the styles that they use.

Second then, how do we define our own styles for the ‘Styles’ menu in the Content Editor? Well, this is a bit more complicated, but there is good documentation out there. Ari Bakker has some good instructions, there’s another (less consise) example from MartyG and there is good documentation on MSDN – though do not believe the top comment, I’ve had my styles working from another CSS file just fine. Do pay attention to the second comment – to see the styles in the menu, you will have to Select some text.

The steps as I found them ultimately were:

1) In your RichHTMLField set the PrefixStyleSheet=”someName”

2) In your styles (whichever one you fancy, as far as I can tell) set up your styles:

.someNameCustom-Heading1 {

...

}

.someNameCustom-Heading2{

...

}

3) Publish.

4) Make sure you’ve selected some text, then choose a style:

Editor Styles Menu

Just as a sidebar, there is a fairly good article on MSDN about “How to Create a SharePoint Server 2007 Custom Master Page and Page Layouts for a Web Content Management Site

Anyway what about the next option….

Creating Pages with the Document Conversions Service

First off, this requires that your servers are setup and running the service and your content types are configured set up for it. That’s not too surprising, and I’m not going to go into that any further. I’m also going to look solely at authoring from Word only, and not InfoPath or XML.

Now, things might get confusing here between CSS styles and Word Styles. For simplicity, from here on I’m going to refer to CSS styles with small s (styles) and Word Quick Styles with a big S and italics (Styles).

Once those are services are set up running, you face the same first problem as with the web page authoring – how do we stop users mucking around with our Styles and formatting, except that this time it’s in Word. Well, Word 2007 lets you do this. First, go to the Manage Styles Menu:

Manage Styles in Word

Then on the ‘Restrict’ tab, set the Styles you want to limit users too. This will password protect your template, so that others can’t just undo these settings. Then get users to create their pages using these Styles – they can’t create new Styles or modify the colour/boldness/formatting of the text directly..

Okay, so what happens to the Styles when we upload and convert the document. Well, that depends on the settings you configure for the conversion:

Styles Settings

You can either strip out the Styles from the document, or keep them. Okay, but what does that mean?

Well, Word has a number of ‘default’ Styles – normal, Heading 1, Heading 2, etc. – and there are style definitions of what they should look like in a stylesheet called ‘RCA.css’ (for Rich Client Authoring). In SharePoint Designer you’ll find this in ‘style library > en-us > core styles’ . This defines a the styles for a bunch of Styles
RCA Styles
Click on the image and take a look. You’ll notice that there are css styles for Heading1-P and Heading1-H – we’ll come back to why there are two of each style.

Anyway, returning to what happens to the Styles – if you decide to ‘Remove CSS <styles> section…’ you’ll get a page where your text is formatted as per the styles in RCA.css. This might be quite different to the Styles in your original Word document! Default Styles (Normal, Heading 1, etc.) will be defined by the CSS styles in RCA.css. If you have extra Styles beyond the ‘default’ ones in Word, then they will not have any style, as they don’t have any definition in the RCA.css file. For example, if I define a Styles in Word called ‘Heading 1 Red’, then my page will use css classes called Heading1Red-P and Heading1Red-H. However, in the RCA.css file, there is no definition for these classes, and hence they’ll be unformatted. You can add them though, or you can put them in another stylesheet, etc..

What if you choose to ‘Store CSS <styles>…’? Well, then the CSS definitions for the Styles get stored with the page, and the out-of-box page layouts put this content into the header – but after the RCA.css file has been referenced, so these styles take precedence. Thus, your document will be styled as defined in the document (well, more or less).

Great! Oh, wait, what if I want to change all of my Heading 1 styles and I’m storing the CSS in the page? Well, that’s a problem – ‘cos each page has it’s own definition. Because of that, I would suggest setting up templates with known Styles , locking them down, defining the css styles for those Styles in a CSS file (like rca.css), and then making sure your document conversion ‘Removes CSS‘. If you have gone down the route of having your styles stored with your page, you might be able to fix things by simply removing the FieldValue control that inserts the styles into the page – for the PageFromDocLayout that comes out-of-box, this control is the PageStylesField.

Anyway, you can see why I’m suggesting locking the Styles on your templates – otherwise you might end up with users creating new Styles which aren’t defined in RCA.css, which is pretty painful if you’re then removing the css styles during conversion .

As a side note, what about inline changes to the format of text – what if I change the format of something without creating a new style? Well, those formats are stored inline in the converted page. If, for example, you made some ‘Normal’ Style text red, you’d get the code…

<span style="color:#FF0000">Normal Style + Red</span>

… in your page. Note that this can’t be overridden by style sheets – and doesn’t seem to be removed by either of the Remove or Store CSS options mentioned above. Best to avoid allowing this (returning us to locking down your template again!)

Now, I said I’d return to the question of why two styles for each Style. Well, the short answer is I’m not sure – but it does seem that in Word when you set up a style it applies both to a paragraph (e.g. paragraph spacing), and to a bit of text (e.g. font/colour, etc.). During conversion it appears that to account for this, two styles are required. The converted document’s HTML looks like …

<p class=Normal-P style="margin-top:3pt;margin-bottom:0pt;direction:ltr;unicode-bidi:normal">

<span class=Normal-H><span class="minorAnsiTheme Normal-H">Normal Style</span></span>

</p>

…so that might give you some idea. (The text in this paragraph is actually the phrase ‘Normal Style’, and the style applied to it is ‘Normal’).

Final note – and this really caught me out – if you convert a document to a page, then you adjust the document conversion settings and you want to reconvert that page, delete and recreate the page. Updating the page does not seem to change the page, perhaps ‘cos you’ve not updated the document itself.

What about using both?

Well, that’s tricky. The structure of the HTML and the styles are different, so you can’t just apply the same styles as is in the RCA.css file. In principle you can us both in your authoring, but you probably do need to have different definitions for the ‘Heading 1’ style in your Content Editor, and ‘Heading 1’ in your RCA.css file. I’ll blog more about this shortly, but right now I’m tired!

Modify the RichHTMLField control on your page layouts

Page Layouts, Breadcrumbs, and the space above the main content area of a page.

Previously, I’ve blogged about some of my investigations into how breadcrumbs work in SharePoint – and how sometimes they’re shown in the ‘Page Title Area’, and sometimes they’re put into the ‘Main Content Area’.

One of our customers was building a page layout, and wanted the breadcrumbs inside the Main content area. They put the following content controls into the page layout file:

<%-- This content tag blanks the 'title' placeholder, which is above the white 'main content area' of a page --%>
<asp:Content ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" />

<%-- This content tag blanks the 'title breadcrumbs' placeholder, which is above the white 'main content area' of a page --%>
<asp:Content ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server"/>

<%-- This is the main content for a page. This content tag is an example only.
Usually there is more formatting and web part zones, other controls, etc.--%>

<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">

<!-- This tag defines the breadcrumb to display. On a normal page (such as defaultlayout.aspx) it is a contained within a table -->
<asp:SiteMapPath ID="ContentMap" Runat="server" SiteMapProvider="CurrentNavSiteMapProviderNoEncode" RenderCurrentNodeAsLink="false" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional"/>

<!-- This tag displays the text of the page's 'Title' that is given when it is created. -->
<SharePoint:FieldValue id="PageTitle" FieldName="Title" runat="server"/>

</asp:Content>

Unfortunately, this resulted in a gap between the top of the page content area, and the bottom of the top navigation:

Page Layout Gap

So, what was missing?

Well, it turns out that another couple of content controls are relevant:

<asp:Content ContentPlaceHolderId="PlaceHolderPageImage" runat="server"><IMG src="/_layouts/images/blank.gif" width=1 height=1 alt=""></asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">
<style>
TD.ms-titleareaframe, .ms-pagetitleareaframe {
height: 10px;
}
Div.ms-titleareaframe {
height: 100%;
}
.ms-pagetitleareaframe table {
background: none;
height: 10px;
}
</style>
</asp:Content>

The first content tag blanks the ‘page icon’ placeholder, which is above and to the left the white ‘main content area’ of a page. It is set to show a 1 pixel transparent image, and it appears that this is to maintain page structure, where setting the content to nothing might allow the table cell to collapse. And I thought that 1 pixel transparent gifs were so 1992.

The second content tag reduces the space available for the ‘page title area’ through CSS. It overrides some of the styles to do this. Of course, this relies on your master page using those styles, or having that structure – so if you’re planning on creating a custom master page, you’d better think of all custom page layouts too. I’m not really convinced about that as design – it seems to me that this makes creating a new, radically different master page even harder, as the page layouts must be rebuilt too.

Page Layouts, Breadcrumbs, and the space above the main content area of a page.

More SharePoint Breadcrumb WTF

Previously I’d posted about SharePoint Breadcrumbs and how they were confusing as hell. I’d discussed how SharePoint publishing pages override the ‘PlaceHolderTitleBreadcrumb’ content control, filling it with blankness, and then supplying their own breadcrumb as part of the page content. That seemed pretty dumb to me… …much more sensible would be to override the ‘PlaceHolderTitleBreadcrumb’ with the breadcrumb we want.

Well, it transpires that I was wrong. What I’ve described is true for some page layouts… and not for others. The Default Master page defines its PlaceHolderTitleBreadcrumb ContentPlaceHolder control as:

<asp:ContentPlaceHolder id="PlaceHolderTitleBreadcrumb" runat="server">
<asp:SiteMapPath SiteMapProvider="SPContentMapProvider" id="ContentMap" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional" runat="server"/>
</asp:ContentPlaceHolder>

This is defining the default breadcrumb on the master page.

For the DefaultLayout.aspx layout page, it defines the content for the page to have:

<asp:Content ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server"/>

That will empty the placeholder on the master page, so no breadcrumb will appear in the usual location – in fact, nothing will. (Note: you will probably want to reduce the blank space that the breadcrumb occupied – otherwise you’ll have a bit gap above your main content area). It then goes on to define (in the PlaceHolderMain Content control):

<td class="ms-pagebreadcrumb" colspan="2">
<asp:SiteMapPath ID="ContentMap" Runat="server" SiteMapProvider="CurrentNavSiteMapProviderNoEncode" RenderCurrentNodeAsLink="false" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional"/></td>
</tr>

There we can see the breadcrumb that appears in the page content.

However, if we look at a different page layout, such as BlankWebPartPage.aspx, we see:

<asp:Content ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server">

<div class="breadcrumb">
<asp:SiteMapPath ID="siteMapPath" Runat="server" SiteMapProvider="CurrentNavSiteMapProviderNoEncode" RenderCurrentNodeAsLink="false" SkipLinkText="" CurrentNodeStyle-CssClass="breadcrumbCurrent" NodeStyle-CssClass="ms-sitemapdirectional"/>

</div>

</asp:Content>

Okay, interesting. So, what’s different about the breadcrumbs? Well, a few things, but the point relevant to whether or not the “> Pages > default.aspx” is displayed in the breadcrumbs – the SiteMapProvider. The CurrentNavSiteMapProviderNoEncode provider doesn’t seem to include the ‘Pages’ bit of the path – hence it is used by the page layouts. The Default.master’s SPContentMapProvider provides a breadcrumb that includes the ‘Pages’.

It is a bit mystifying why some page layouts blank the PlaceHolderTitleBreadcrumb while other override it – it would have been really nice if they worked consistently. And, as a side note, if you create a page layout and find that your breadcrumbs include the “> Pages > default.aspx” bit, then 1) make sure you’re providing content to override the PlaceHolderTitleBreadcrumb, and 2) make sure that it uses the CurrentNavSiteMapProviderNoEncode navigation provider.

More SharePoint Breadcrumb WTF

SharePoint Branding or "Pimp my SharePoint"

One of the things that customers appear to want, and will like about SharePoint is the ability to ‘brand’ or ‘skin’ it. For some reason, it’s something that people always get hung up on – what it looks like, not how it works – and I don’t expect we will have many projects that don’t have the question of branding/skinning/customisation. But what does this mean, how does it work, and what are the limitations? Continue reading “SharePoint Branding or "Pimp my SharePoint"”

SharePoint Branding or "Pimp my SharePoint"