Date-aware Theme Header Images

Sunday, 29 March 2009 01:56 PM
by Coose

Update: This post is outdated.  It kinda sucks.  Please don't use this.  A much, much, much simpler solution is posted here.

I've always really liked the subtle holiday themed logos that Google puts on their site.  It's not really hard, so I modified my theme to make the header images change on certain days.

It's not terribly complicated, but it shows a few things that might be of some help.

Configuration

The first step is to tell the BlogEngine.NET theme when to change the header image.

I initially was going to take the quick and easy route, and just use the appSettings section of the web.config file.  I really needed three pieces of information for each date-aware header image, so the appSettings really is kind of a hack.

So I created a custom configuration section in my personal BlogEngine.NET assembly.

public class TimelyHeaderConfigurationSection : ConfigurationSection

{

    public TimelyHeaderConfigurationSection()

    {

    }

 

    [ConfigurationProperty("Enabled", IsRequired = false, DefaultValue = true)]

    public bool Enabled

    {

        get { return (bool)this["Enabled"]; }

        set { this["Enabled"] = value; }

    }

 

    [ConfigurationProperty("DefaultUrl", IsRequired = false)]

    public string DefaultUrl

    {

        get { return (string)this["DefaultUrl"]; }

        set { this["DefaultUrl"] = value; }

    }

 

    [ConfigurationProperty("Headers", IsDefaultCollection=false)]

    [ConfigurationCollection(typeof(TimelyHeaderCollection), AddItemName="add", ClearItemsName="clear", RemoveItemName="remove")]

    public TimelyHeaderCollection Headers

    {

        get

        {

            return this["Headers"] as TimelyHeaderCollection;

        }

    }

}

Enabled obviously turns on or off the functionality.

DefaultUrl allows an image URL to be specified in the event that the current date does not have any matching entries.  You could just leave the off and use the default functionality of the theme.  This is really unnecessary…I have plans for using it for something in the future.

Headers is a collection of TimelyHeader configuration elements defining when to display other header images.  The ConfigurationCollection attribute defines what class will handle the collection of child configuration elements.  It is a standard clear/add/remove collection.

 

public class TimelyHeaderCollection : ConfigurationElementCollection

{

    public override ConfigurationElementCollectionType CollectionType

    {

        get

        {

            return ConfigurationElementCollectionType.AddRemoveClearMap;

        }

    }

 

    public TimelyHeaderElement this[int index]

    {

        get { return (TimelyHeaderElement)BaseGet(index); }

        set

        {

            if (BaseGet(index) != null) BaseRemoveAt(index);

            BaseAdd(index, value);

        }

    }

 

    protected override ConfigurationElement CreateNewElement()

    {

        return new TimelyHeaderElement();

    }

 

    protected override object GetElementKey(ConfigurationElement element)

    {

        return ((TimelyHeaderElement)element).Url;

    }

 

    public void Add(TimelyHeaderElement element)

    {

        BaseAdd(element);

    }

 

    public void Clear()

    {

        BaseClear();

    }

 

    public void Remove(TimelyHeaderElement element)

    {

        BaseRemove(element.Url);

    }

 

    public void Remove(string name)

    {

        BaseRemove(name);

    }

 

    public void RemoveAt(int index)

    {

        BaseRemoveAt(index);

    }

}

Nothing interesting or insightful here.

And a simple configuration element:

public class TimelyHeaderElement : ConfigurationElement

{

    [ConfigurationProperty("Url", IsRequired = true)]

    public string Url

    {

        get { return (string)this["Url"]; }

        set { this["Url"] = value; }

    }

 

    [ConfigurationProperty("BeginDate", IsRequired = true)]

    public DateTime BeginDate

    {

        get { return (DateTime)this["BeginDate"]; }

        set { this["BeginDate"] = value; }

    }

 

    [ConfigurationProperty("EndDate", IsRequired = true)]

    public DateTime EndDate

    {

        get { return (DateTime)this["EndDate"]; }

        set { this["EndDate"] = value; }

    }

}

 

Theme Modifications

In order to make the header images (a.k.a. "Timely Headers") work, I had to make some changes to my BlogEngine.NET theme.  My theme is based on the "Inove" BlogEngine theme.

  • Replaced the HTML div, <div id="header">, with an ASP.NET panel, <asp:Panel runat="server" CssClass="header" ID="HeaderControl">.
  • Changed my theme style sheet to change the id header (#header) to a class (.header).
  • Added the following code in the site.master Form_Load method.

TimelyHeaderConfigurationSection section =

    (TimelyHeaderConfigurationSection)ConfigurationManager.GetSection("TimelyHeaders");

 

if (section == null) return;

if (section.Enabled == false) return;

 

// if we have more than one, we want the one that has the LATEST begin date.

TimelyHeaderElement header =

    section

    .Headers

    .Cast<TimelyHeaderElement>().Where(e =>

        e.BeginDate <= DateTime.UtcNow && e.EndDate >= DateTime.UtcNow)

    .OrderBy(e => e.BeginDate)

    .FirstOrDefault();

 

if (header != null)

{

    this.HeaderControl.BackImageUrl = header.Url;

}

else if (!string.IsNullOrEmpty(section.DefaultUrl))

{

    this.HeaderControl.BackImageUrl = section.DefaultUrl;

}

Note that I'm using LINQ, so your web application will have to have LINQ assemblies referenced.

Configure for Use

Register the configuration section in the configSections section:

<section name="TimelyHeaders"

        type="Funkymule.BlogEngine.Configuration.TimelyHeaderConfigurationSection, Funkymule.BlogEngine"/>

Add date ranges for specific headers in the registered configuration section:

<TimelyHeaders Enabled="true">

    <Headers>

        <clear />

        <add Url="~/Images/HamBdayHdr.jpg"

            BeginDate="3/20/2009"

            EndDate="4/3/2009" />

    </Headers>

</TimelyHeaders>

 

Now, when my blog pages load between March 20th and April 3rd, visitors will be greeted with a reminder of my son's birthday.

Note that when two Timely Headers are configured for a specific date, the one that has a BeginDate later than the other is used.

Simple, but effective.

Update: This post is outdated.  It kinda sucks.  Please don't use this.  A much, much, much simpler solution is posted here.

Comment on this
Development

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading