Making of 'blogCalendar'

Rating: 4,3 / 5 stars - 3 vote(s).



Yeah, I know what you're about to say. Why reinventing the wheel if you've got plenty of examples available on the net?

I just wanted to get my hands dirty on creating a small add-on for my own site. I'll list the steps I've taken to create my own blog calendar and what design decisions I've taken along.

I wanted to create a calendar based on the standard asp.net calendar control and highlighting those days on which I've created one or more blog post. As an extra, I wanted to have some extra flexibility by adding support for alternate templates.

Alternate templates are a way of telling the umbraco system not to use the template defined and set at node creation/update, but to use a different template (even at runtime). In order to use an alternate template at run-time, you'll need to tweak the url a bit, so umbraco will keep up its name and replace the 'standard' template by its runtime equivalent.

For example: Let's assume you'll have a content node listening at url

http://www.yadayada.be/name-of-the-node.aspx

and a template called 'Simple Template' (Alias='simpleTemplate').

At runtime, you could change the rendered output by changing the url into http://wwww.yadayada.be/name-of-the-node/complexTemplate.aspx

Quite simple, just insert the name of the alternate template before the '.aspx' extension and you're set. You've got to love umbraco's flexibility already now, don't you?

Back to our blog calendar add-on now. Here's a list of steps to get the blogCalendar up-and-running on your site:

1. Create a new vs2005 asp.net web application project.
2. Add a new web user control to the project
3. Drag'drop a standard asp.net calendar control from the toolbox onto the designer. At this point, you can tweak the design to match the design of your site.
4. Go to code behind, and add 2 public properties.

Public properties will be used as a gateway for communication between several elements of the system (I'll explain in a minute). First property will hold the id of the node for the blog, the second property will be used to set the name for the alternate template.

   1:          private int blogNodeId;
   2:          public int BlogNodeId
   3:          {
   4:              get { return blogNodeId; }
   5:              set { blogNodeId = value; }
   6:          }
   7:   
   8:          private string blogDayTemplate;
   9:          public string BlogDayTemplate
  10:          {
  11:              get { return blogDayTemplate; }
  12:              set { blogDayTemplate = value; }
  13:          }

5. Add some extra code for the page's OnLoad and the calendar's DayRender event

   1:          protected void Page_Load(object sender, EventArgs e)
   2:          {
   3:              string queryString = umbLib.RequestServerVariables("QUERY_STRING").Replace("umbPage=/", "");
   4:              blogBaseFriendlyUrl = umbLib.NiceUrl(blogNodeId).Replace(urlExtension, "");
   5:   
   6:              Trace.Write("Querystring = " + queryString);
   7:              Trace.Write("blogBaseFriendlyUrl = " + blogBaseFriendlyUrl);
   8:   
   9:              
  10:              Calendar.DayRender += new DayRenderEventHandler(OnCalendarDayRender);
  11:   
  12:              try
  13:              {
  14:                  if (ShouldRenderBasedOnBlogDate(queryString))
  15:                      Calendar.VisibleDate = new DateTime(GetYear(queryString), GetMonth(queryString), 1);
  16:                  else
  17:                      Calendar.VisibleDate = new DateTime(GetCurrentYear(), GetCurrentMonth(), GetCurrentDay());
  18:              }
  19:              catch
  20:              {
  21:                  Calendar.VisibleDate = new DateTime(GetCurrentYear(), GetCurrentMonth(), GetCurrentDay());
  22:              }
  23:          }
 
   1:          void OnCalendarDayRender(object sender, DayRenderEventArgs e)
   2:          {
   3:              if (e.Day.IsOtherMonth)
   4:              {
   5:                  e.Cell.Text = string.Empty;
   6:                  return;
   7:              }
   8:   
   9:              XPathNodeIterator blogNodeIterator =
  10:                  umbLib.GetXmlNodeByXPath("root/descendant-or-self::node[@id=" + blogNodeId
  11:                          + "]/descendant-or-self::node[@nodeTypeAlias=\"umbracoBlogPost\""
  12:                          + " and number(substring(@createDate,1,4))=" + e.Day.Date.Year
  13:                          + " and number(substring(@createDate,6,2))=" + e.Day.Date.Month
  14:                          + " and number(substring(@createDate,9,2))=" + e.Day.Date.Day + "]");
  15:   
  16:              if (blogNodeIterator.Count > 0)
  17:                  e.Cell.Text = "<a href=\"" + BuildFriendlyUrl(e.Day.Date) + "\">" + e.Day.DayNumberText.ToString() + "</a>";
  18:              else
  19:                  e.Cell.Text = e.Day.DayNumberText.ToString();
  20:          }
 

6. Build the project, ending up with a compiled .net assembly dll and a single web user control.

Installing the blogCalendar is almost like a simple copy'n'paste operation. First, copy the assembly to the /bin folder of the root. Our web user control goes into the /usercontrols directory.

7. Log in into the umbraco admin backend and go to the 'Developer' section. Right-click on 'Macro' and select 'Create'. Call the macro whatever you'd like it to be.

First step - installation

I called mine 'Umbraco Blog Calendar' with alias 'UmbracoBlogCalendar'. Find the user control in the dropdown. Hit 'Save' icon.
After saving, click 'Browse properties' to get a list of public properties in the user control.

Step 2 - Choose properties

Hit 'Save Properties' button, and dialog will close. Go to the 'Parameters' tab and change the types for the parameters.

Step 3 - Change type of properties

On any template you wish to include the macro, click the 'Insert macro' icon. Choose 'Umbraco Blog Calendar' from the dropdown.

Step 4 - Choose macro

Add values for the listed properties and hit 'OK' button.

Step 5 - Add property values

Macro gets inserted in the template.

Step 6 - Macro inserted in template

As I said before, the two properties can be used to pass info from the system to the user control. In this case, I'm telling the blogCalendar that the topmost node will be node with id=1053, whereas the alternate template is listening to 'umbracoBlog frontpage'. Both values will be used to build the blogCalendar at run-time.

You're all set now. Enjoy your calendar.

Download sample project file .