Advertisement

Getting Started with Umbraco: Part 2

by

In .NET, a masterpage is a template for content pages, where a series of ASPX pages that all use the same masterpage can all share the same base code.


Also available in this series:

  1. Getting Started with Umbraco: Part 1
  2. Getting Started with Umbraco: Part 2
  3. Getting Started with Umbraco: Part 3
  4. Getting Started with Umbraco: Part 4
  5. Getting Started with Umbraco: Part 5

A masterpage can then have one or more contentPlaceHolders defined and each ASPX page that uses that masterpage need only define the code that is within the contentPlaceHolder. Masterpages can also be nested, which is how they will be structured in our example site.


Defining the Code in our Base Page Template

The Base Page, remember this is the Template and Document Type that all subsequent pages will inherit from, should contain just those elements common to all pages of the site. Open up the BasePage.master file in Visual Web Developer Express (VWD). It will already have a little ASPX code in the file including an <asp:Content> element. This element points to an <asp:ContentPlaceHolder> element in one of Umbraco's masterpages.

It is possible to add the code to the masterpages entirely through the Umbraco back-end; when you select one of the Templates in the Settings area, it loads a copy of the file into the right-hand panel of the back-end for editing, this feature more useful for making small changes and updates to the masterpages, and for inserting macros or items. When we use a full .Net IDE we get intellisense and a range of other features that are not present in Umbraco so creating the masterpages will usually require editing in both areas.

Add the following code within the <asp:Content> element:

<!DOCTYPE HTML> 
	<html lang="en"> 
		<meta charset="utf-8" /> 
		<head> 
			<title><umbraco:Macro Alias="pageTitle" runat="server"></umbraco:Macro></title> 
			<!--[if lt IE 9]> 
				<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> 
			<![endif]--> 
			<link rel="Stylesheet" href="/css/site.css" /> 
		</head> 
		<body> 
			<form runat="server"> 
				<header> 
					<hgroup> 
						<h1><a class="accessible-hidden logo" href="/" title="Return To Home Page">The company name</a></h1> 
						<h2>This is the company's tag line</h2> 
					</hgroup>                 
					<nav> 
						<ul> 
							<li><a href="/" title="Home">Home</a></li> 
							<li><a href="/" title="About Us">About Us</a></li> 
							<li><a href="/" title="News">News</a></li> 
							<li><a href="/" title="Contact Us">Contact Us</a></li> 
						</ul> 
					</nav> 
				</header> 
 
				<div id="innerContent" class="clear-float"> 
					<asp:ContentPlaceHolder id="BaseContent" runat="server"></asp:ContentPlaceHolder> 
				</div> 
				<footer> 
					<nav> 
						<ul> 
							<li><a href="/" title="Home">Home</a></li> 
							<li><a href="/" title="About Us">About Us</a></li> 
							<li><a href="/" title="News">News</a></li> 
							<li><a href="/" title="Contact Us">Contact Us</a></li> 
						</ul> 
					</nav> 
	                <p>Copyright The Company <%=DateTime.Now.Year %></p> 
				</footer> 
			</form> 
	        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> 
		</body> 
	</html>

Save the file. Let's take a look at what we've got. It's in HTML5 format, as we can tell straight from the minimal DOCTYPE and meta charset element. It's not essential to use HTML5, but we may as well right? In the <head> of the page we've linked to a style sheet (which we haven't created yet, but will at some point later on) and a <title> element. The <title> contains our first Umbraco tag and points to a macro. Don't worry too much about this for now, we haven't discussed macros yet and these will be covered in much more detail in a later part of the series. The content of the page is wrapped in a <form> element with the runat attribute set to server, which is standard practice for .Net sites. We also include a link to the HTML5shiv file on Google code so that IE8 or below is able to display our HTML5 elements correctly.

Next we have a <header> element which contains a <hgroup> element for the main site heading and tag line (composed of <h1> and <h2> tags respectively), and a <nav> element containing the main navigation for the site, which will be built from a standard unordered-list. The HTML shown for the main navigation will not actually be used in the site's final form, it is listed here as a guide to how the HTML should be when it is built automatically using another macro. It is useful to add the basic structure for dynamically built elements, in case they need to be styled before the dynamic bits are added. This is especially important if you're working as part of a team and someone else will be handling all of the (fun) back-end stuff.

We then have a <div> element which contains an <asp:ContentPlaceHolder>. The <div> has an id for styling purposes, and the <asp:ContentPlaceHolder> has an id attribute so that it can be populated with other pages (or masterpages). It also has the runat="server" attribute because it is an ASPX element handled by the server. Notice that some of our elements are given class names for when we come to style the site near the end of the series.

We also have a <footer> element which contains another copy of the navigation (again the HTML is provided at this stage mainly for styling purposes and as an example of how it will eventually appear in the browser when the pages are served), and a copyright statement. The copyright statement contains a little snippet of C#; all this does is output the current year in standard 4 digit format, so that it always reflects the year that the page is viewed. Finally we link to the Google-CDN hosted version of jQuery, as we'll need this to add some behaviour to our site in the final part of the series.


Coding the Home Page

Next we can add the code that will make up the home page. If we open up the HomePage.master file in VWD we can see that it has already been nested under BasePage.master (the BasePage.master file is set as the MasterPageFile in the Master declaration at the top of the file), we just need to change the ContentPlaceHolderID of the <asp:Content> element so that it points to the <asp:ContentPlaceHolder> element we added to the BasePage.master:

<asp:Content ContentPlaceHolderID="BaseContent" runat="server"> 
 
	</asp:Content>

Now add the following code to the <asp:Content> element shown above:

<p id="introText"><umbraco:Item field="introText" runat="server" /></p> 
 
	<umbraco:Item field="bannerImage" xslt="concat('&\lt;img src=&\quot;',umbraco.library:GetMedia({0}, false())/umbracoFile, '&\quot; alt=&\quot;',umbraco.library:GetMedia({0}, false())/@nodeName, '&\quot; /&\gt;')" xsltDisableEscaping="true" runat="server"/> 
 
	<div id="hero"> 
	    <div id="viewer"> 
	        <div id="slider"> 
	            <umbraco:Macro Alias="heroPanels" runat="server"></umbraco:Macro> 
	        </div> 
	    </div> 
	    <ul id="ui" class="clear-float"> 
	        <li id="prev"><a href="#" title="View Previous Panel">Previous</a></li> 
	        <li id="next"><a href="#" title="View Next Panel">Next</a></li> 
	    </ul> 
	</div>

This masterpage contains another type of Umbraco element – the Item. The first item we use sets the introductory text on the page. Remember, we defined this as a property of the Home Page Document Type in part one of this series and set it to a data type of Richtext editor. The <umbraco:Item> element here in the template will display the contents of whatever is entered into the rich text editor when we create a content node for the home page in the back-end.

It should be a little clearer now how the properties in the Document Types relate to the elements that end up on our pages, but don't worry if it isn't 100% crystal clear at this point – we still haven't created any actual pages yet, but when we do the final part of the puzzle should click neatly into place.

Next we have an image element; because we're using a media picker (I'll explain exactly what a media picker is when we create the page) the code for this is much more complex than what we have seen so far. One of the sections in the Umbraco back-end is the Media section where all of the media content for a site can be uploaded and stored. Like other resources for the site, each media item is a node in the node tree and is given a name when the media item is added to the CMS.

When we add the <img>element, we use an <umbraco:Item> similar to the introText, but we need to use a snippet of inline XSLT code and a couple of snippets of HTML to actually get the path of the image stored in the media library. The XSLT snippet makes use of the concat() method, which accepts an comma delimited array of strings to concatenate, to build the <img> element. Within this array we use the HTML entities and mark up to build the element manually and also use a function from the umbraco.library class. The function is GetMedia and allows us to obtain the path to the mage in the Media library (there is a matching folder in the Umbraco file system which all of the media items are stored in) using the umbracoFile property, and the name of the node using @nodeName. Note that to get the example code above to display correctly I had to insert \ characters in the HTML entities. Remove those if copy and pasting into your own files.

Finally, we add some basic mark-up for the hero panel including an outer container (the <div> with an id of hero), a <div> each for the #viewer and #slider elements, and a simple UI that will allow the different panels of content to be navigated. The #slider element also contains an <umbraco:Macro> element, so we will build this part of the hero panel using an XSLT macro that we'll create in a later part of the series. The hero panel will be initially built from XSLT and the mark-up shown here, and will then be made to work with script.


Creating the Content Template

Our content pages are relatively simple and are built using a single property from the Content Document Type. In the masterpage file change the ContentPlaceHolderID of the <asp:Content> element to BaseContent exactly as we did for the home page:

 
<asp:Content ContentPlaceHolderID="BaseContent" runat="server"> 
 
</asp:Content>

Then add the following code to the <asp:Content> element:

<div id="pageCopy"><umbraco:Item field="pageCopy" runat="server" /></div>

That's it, that's all we'll use in our content page template. In reality, a content page would probably be much more complex, but for our simple example it should suffice. We've used an outer containing <div> for this <umbraco:Item> because the item is linked to a Richtext editor and so could contain many different types of content.


The News Templates

Our NewsList template will be almost as basic as our Content template as the page will largely be built dynamically using an XSLT macro. Don't forget to update the ContenPlaceHolderID to BaseContent as we have in our other templates and then add the following elements to the placeholder:

<section id="newsList"> 
		<h1>Recent News from The Company</h1> 
		<umbraco:Macro Alias="newsList" runat="server" /> 
	</section>

On this page we have a <section> element, which is home to the main page heading and the macro that builds the news list. This is all we need in this template so let's move on to the next and final one; the NewsItem. Again, change the ContentPlaceHolderID to BaseContent and then add the following code to the placeholder:

<article id="newsItem"> 
		<header> 
			<h1><umbraco:Item field="headline" runat="server" /></h1> 
			<ul class="clear-float"> 
				<li>Posted on <umbraco:Item field="date" formatAsDate="true" runat="server" /></li> 
				<li>By <umbraco:Item field="creatorName" runat="server" /></li> 
			</ul> 
		</header> 
		<div id="newsContent"> 
		<umbraco:Item field="storyImage" xslt="concat('&\lt;img  src=&\quot;',umbraco.library:GetMedia({0}, false())/umbracoFile, '&\quot; alt=&\quot;',umbraco.library:GetMedia({0}, false())/@nodeName, '&\quot; /&\gt;')" xsltDisableEscaping="true" runat="server"/> 
		<div id="newsText"><umbraco:Item field="newsText" runat="server" /></div> 
		</div> 
	</article> 
 
	<nav id="newsNav"> 
		<umbraco:Macro Alias="newsNav" runat="server" /> 
	</nav>

Our NewsItem template is a little more complex than most of the others. The main container for the news story is an <article>, which contains a <header> for the headline and some information about the news story such as its date and author. The date, which is shown in the first <li>, is linked to the Datepicker field we added to the corresponding Document Type for this page type. We set the formatAsDate attribute to true which formats the date nicely instead without a time string added to the end. The author is obtained using the creatorName property that is automatically added to nodes (pages) when they are created in the back-end.

The body of the article is an outer container <div> which uses the newsImage field (this is essentially the same as the banner image on the home page which also uses a Media picker. Again the HTML entities have backslashes in them so that they display correctly here) and a <div> that uses an <umbraco:Item> linked to the newsText field. We also create a secondary <nav> element that will allow the visitor to navigate directly from the current news page to other news pages without having to go back to the news list. This will be built from a macro, which we'll look at in the next part of this series.


Adding Pages

So we've spent a good couple of hours at least so far setting things up (more if you had to install VWD + SQL Server), so let's add some pages already! In an Umbraco site, there actually aren't any individual 'pages' as such. Don't think to yourself - "I need this page to do something unique so I can add this or that to the underlying page" – it just doesn't work like that, there are no underlying pages. Instead of pages, we have content nodes in the node tree (specifically, nodes in the Content section of the CMS backend), and data in the database. There are individual URLs stored in the database, and each node is mapped to a URL, so when a visitor types the address of a page, or navigates around the site, the CMS will check which URL was requested and build the page on the fly, using its Document Type and template.

So, to create the home page of the site, go to the Content section of the CMS, right-click the Content folder in the top left panel and choose Create. In the dialog that appears, enter Home as the Name and choose Home Page as the Document type:


Once we hit the Create button in the dialog, the new node will be created and displayed in the top left panel of the CMS, and will have a little orange star to the right of it. This indicates that the node has been saved, but not published. In the right hand panel of the CMS we see the tabs and fields that we defined in the Document Type in part 1. The Content tab is displayed by default as it is the first tab, the first property we defined was the Intro Text property, which maps directly to the textarea at the top of the Content tab. We also defined the Banner Image property, which maps directly to the Media picker control shown below the textarea.

The home page content node will also inherit a property from the Base Page document type -the Domain Name - which can be seen on the Properties tab. Go to the Properties tab now. There are several important properties here that are created automatically by Umbraco including the Name of the node, which is an editable field so that we can easily change the node name at any point, and the Document Type and Template in use. There are other useful properties such as the creator of the node and the publish date. Enter The Company in the Domain Name field (this could take the format The Company, or an actual URL such as www.thecompany.com, it doesn't make a difference as it will simply be used for the title of the page).

Both the Intro Text and the Banner Image are mandatory properties, so they will both need to be populated before we can publish the page. The Intro Text is easy; we just start typing in the textarea. We can do some basic formatting using the Richtext editor buttons at the top of the tab, but essentially we just complete this property, or field, by typing. The Banner Image is slightly (but not much more) complex and to complete it, we'll need to work briefly with another section of the CMS – the Media library.


The Media Library

The Media library is a repository for all media resources, such as images, videos, sound files or other embedded files or documents. Our Banner Image field for the Home Page uses a Media picker, control which opens up a dialog showing the media library and allows the end administrator of the site to visually choose the image they want to use. Before that can happen however, there need to be items in the media library that can be picked.

To add an item to the media library we just choose the Media section by clicking the icon in the lower left panel of the back-end and then once the media section node has loaded in the top left section, we right-click the Media folder and choose Create from the menu. In the dialog that appears we can set a name for the image (remember that the name we give the node is used in the alt attribute of the image when it is displayed on the home page), and choose the Media Type. There are three predefined types we can pick from; a folder which can be useful when we have many different media items that we want to categorise and store in an orderly fashion, a general File type, or Image, which we will use in this instance. Other Media Types can easily be created in the Settings section.

Once the Create button in the dialog has been clicked, the new image item will be created and the right panel of the editor will be filled with some properties including an upload button. We should click the upload button to choose the file from our computer that we want to upload (I have a pre-made image ready on my desktop to upload). Once you have selected the image to upload and clicked the save icon in the toolbar at the top of the right panel, the image will become part of the media library and will be listed as a node in the media node tree. A thumbnail for the image will also be created and shown in the properties panel at the right, along with some of the image attributes:


Now the image is ready to be picked, so go back to the Content section and select the Home node that we created earlier. In the Banner image field below the textarea click the choose link to open the picker, which will appear in a dialog. Click the The Company Does This! node in the picker and it will be set in the Banner image field. The Home node can now be published, so click the icon of the world with a disk in front of it to save and publish the page.

That's it; you made your first Umbraco page! You can view the new page by clicking the Preview icon (the page with the magnifying glass on it) to see it in preview mode, or you can just open up a new tab in your browser, copy the URL of the back-end, paste it into the new tab and knock off everything after the port number.

The page is totally un-styled at this point, but you should find that the intro text and image we set in the back-end are displayed on the page, along with the mark up from the Home.master and Base Page templates. The <umbraco:Item> elements have all been populated, but any <umbraco:Macro> elements won't have been populated yet as we need to write some XSLT for these.


Summary

In this part of the tutorial, we reviewed how Umbraco templates work (they represent .Net masterpages), and how they are nested for maximum code-reuse. Now that we've created a page, we've seen how the Document Types, templates and nodes work together to create the properties we can edit in the back-end, and the pages that our visitors will see.

In the next part of this series we'll create the rest of the pages for the site and then start writing the XSLT that will build the top and bottom navigation, and the hero panel, among other things.

Advertisement