Tutorial - Building NivoSlider Extension (Part 2)

Creating Repository

HTML code we added to site.master can be moved to user control (1), so we’ll need just drop control on the page and be done. But some new themes use Razor instead of WebForms – for those to work we can provide HTML helper (2) do the same thing control does for WebForms. And also we want slider be available in the posts and pages, for that functionality we’ll have to use extension (3). Having planned 3 distinct UIs, it makes sense to abstract common functionality and make UI as light as possible. So lets start by moving that hard-coded list of images into its own class. Open  ~/app_code/extensions folder and create new folder inside it called “NivoSlider”. Then add new class “Repository.cs” – here what it looks like:

namespace rtur.net.NivoSlider
{
  public class Repository
  {
    public static string GetSlider(string id, string width = "960", string height = "370")
    {
      var div = "<div id=\"{0}\" style=\"width: {1}px; height: {2}px;\">";
      div += "<a href=\"#\">";
      div += "<img runat=\"server\" src=\"~/image.axd?picture=Slider/sample1.png\" width=\"{1}\" height=\"{2}\" alt=\"\" />";
      div += "</a>";
      div += "<a href=\"\">";
      div += "<img runat=\"server\" src=\"~/image.axd?picture=Slider/sample2.png\" width=\"{1}\" height=\"{2}\" title=\"sample two\" alt=\"\" />";
      div += "</a>";
      div += "</div>";
      div += "<script type=\"text/javascript\">$(window).load(function (){{ LoadSlider('#{0}');}});</script>";

      return string.Format(div, id, width, height);
    }
  }
}

For now, it will return same hard-coded list with two images – we’ll take care about data layer later. As far as our UI concerned, we ready to roll – call to NivoRepository.GetSlider(id, width, height) will return HTML that represents slider on the page. Each UI will set control ID and optionally image size so every slider can behave independently.

Custom User Control

Because all data coming from repository, control is just a gateway to output it in the right place. Create a new class called “NivoControl.cs” and put it in the ~/app_code/controls folder. The code is below – and there is not a whole lot of it:

namespace rtur.net.NivoSlider
{
    using System.Web.UI;

    public class NivoControl : Control
    {
        public string Width = "960";
        public string Height = "370";

        public override void RenderControl(HtmlTextWriter writer)
        {
            writer.Write(Repository.GetSlider(ID, Width, Height));
        }
    }
}

To use this code, you would need to register it in the header and then put a control tag anywhere inside any .aspx or .master page. Here is an example:

<@ Register TagPrefix="blog" Namespace="rtur.net.NivoSlider" %>
<blog:NivoControl ID="slider1" Width="750" Height="280" runat="server" />

Razor HTML Helper

For Razor theme, we can provide a helper instead of control. This goes to ~/app_code/helpers and class name will be NivoHelper.cshtml. And code is even simpler - single method that takes same 3 parameters and passes them to repository, and returned HTML string streamed to response:

@using BlogEngine.Core
@using rtur.net.NivoSlider

@helper GetSlides(string id, string width = "960", string height = "370")
{
    __razor_helper_writer.Write(Repository.GetSlider(id, width, height));
}

Here how you would use it from Razor theme (site.cshtml in Garland-Revisited theme for example):

@Helpers.NivoHelper.GetSlides("slider2", "750", "280");

Extension

Controls and Helpers are good when you design a theme and want to add slider as part of this theme. In this case, slider sort of static – you define a place where it will show up, set size, style it properly and only thing left for blogger is to add-remove slides that show up inside slider. Not bad, but what if someone wants to show slider inside post or page? Use it as regular photo slideshow? Well, to be fair with BlogEngine.NET you could embed control directly into the post like so:

[ usercontrol: ~/path/to/control.ascx ]

But it doesn't match our requirements very well. Fortunately, extension with token replacement function is very easy to implement – so open ~/app\_code/extensions and add new class NivoSlider.cs:

namespace rtur.net.NivoSlider
{
  using System.Text.RegularExpressions;
  using BlogEngine.Core;
  using BlogEngine.Core.Web.Controls;

  [Extension("jQuery Image Slider for BlogEngine 2.5+", "0.0.0.2", "<a href=\"http://rtur.net/blog\">rtur.net</a>")]
  public class NivoSlider
  {
    public NivoSlider()
    {
      Post.Serving += PublishableServing;
      Page.Serving += PublishableServing;
    }

    private static void PublishableServing(object sender, ServingEventArgs e)
    {
      const string regex = @"\[ SLIDER:.*?\]";
      var matches = Regex.Matches(e.Body, regex);

      if (matches.Count == 0) return;

      foreach (Match match in matches)
      {
        var width = "650";
        var height = "220";

        string[] options = match.Value.Replace("[ SLIDER:", "").Replace("]", "").Trim().Split(':');

        if (options.GetUpperBound(0) > 0)
          width = options[1];

        if (options.GetUpperBound(0) > 1)
          height = options[2];

        e.Body = e.Body.Replace(match.Value, Repository.GetSlider(options[0], width, height));
      }
    }
  }
}

The extension will run every time post or page is serving because we subscribed for both serving events in the class constructor. It will parse post content and replace pre-defined token with slider HTML from repository.

To use this extension, blogger will use this token: [ SLIDER:slider1:750:280 ] or simply [ SLIDER:slider1 ] if default size works fine. It can be inserted anywhere in the post or page. (No gaps in the [ SLIDER ] tokens - gaps here only to prevent rendering as real sliders).

In the next part we'll provide UI to store and maintain image repository.

About RTUR.NET

This site is all about developing web applications with focus on designing and building open source blogging solutions. Technologies include ASP.NET Core, C#, Angular, JavaScript and more.