Writing extensions for BlogEngine 1.4 (part 4)

ex_5-4_thumb.png

Default admin interface for extensions in BlogEngine works fine in most cases and very easy to use. But sometimes you just got to get creative, right? That means, you want no limits. Obviously, some of simplicity will be lost – but still it is surprisingly easy to get along using plug-and-play BlogEngine architecture. Lets say, we ran into nice DHTML color picker and want to use it in the admin page for our extension. We want admin page look like this picture – it should allow us to enter a word, size and color. This values will be saved in the extension manager, so we don’t have to deal with databases or file system – usual BE stuff. And when you click “Color picker” button, nice color picker will show up and you can visually select value for a color.

ex_5-2_thumb.png As you can imagine, few non-standard issues here. Control itself comes with java scripts, CSS and images. So first thing first – we download control and put all files in the “Example_05” folder in the blog’s root. Then we need to create custom admin page (Admin.aspx) to host admin interface. It inherits from admin master page, so it looks like part of the control panel. It is custom – you can use any controls ASP.NET let you to use in the page, any third party controls etc. In this case, we’ll use standard ASP.NET controls and then call color picker function on button click.

<%@ Page Language="C#" MasterPageFile="~/admin/admin1.master" AutoEventWireup="true" CodeFile="Admin.aspx.cs" Inherits="audio_Admin" Title="Untitled Page" %>  
  <asp:Content ID="Content1" ContentPlaceHolderID="cphAdmin" Runat="Server">
  <br />
  <div class="settings">
      <h1>Settings: Example_05</h1>
      <div id="formContainer" runat="server" class="mgr">
          <div id="lblWord" style="width:120px; height:20px; float:left;" runat="server"></div>&amp;nbsp;
          <asp:TextBox ID="txtWord" runat="server" MaxLength="6"></asp:TextBox>
          <br />
          <div id="lblSize" style="width:120px; height:20px; float:left;" runat="server"></div>&amp;nbsp;
          <asp:TextBox ID="txtSize" runat="server" MaxLength="6"></asp:TextBox>
          <br />
          <div id="lblColor" style="width:120px; height:20px; float:left;" runat="server"></div>&amp;nbsp;
          <asp:TextBox id="rgb2" runat="server" />
          <asp:Button id="btnColPicker" runat="server" text="Color picker" />
          <br />
          <br />
          <div style="margin-left:128px">
              <asp:Button ID="btnSave" runat="server" onclick="btnSave_Click" />
          </div>
      </div>
  </div>
  </asp:Content>

Server-side code is simple, with a few useful tricks. We add client click event to ASP.NET button to call JavaScript function to show color picker. Then we programmatically reference JavaScript and CSS files in the code and add them to the page header. On page load and button save click we do usual Extension Manager technic loading and saving values using data store.

public partial class audio_Admin : System.Web.UI.Page
{
    static protected ExtensionSettings _settings = null;
    protected void Page_Load(object sender, EventArgs e)
    {
      btnColPicker.OnClientClick = "showColorPicker(this," + rgb2.ClientID + "); return false;";
      BuildHeader();
      if (!Page.IsPostBack)
      {
        _settings = ExtensionManager.GetSettings("Example_05");
        BindForm();
     }
    }
    protected void btnSave_Click(object sender, EventArgs e)
    {
      _settings.UpdateScalarValue("word", txtWord.Text);
      _settings.UpdateScalarValue("size", txtSize.Text);
      _settings.UpdateScalarValue("color", rgb2.Text);
        ExtensionManager.SaveSettings("Example_05", _settings);
      Response.Redirect(Request.RawUrl);
    }
    protected void BindForm()
    {
      btnSave.Text = Resources.labels.saveSettings;
      txtWord.Text = _settings.GetSingleValue("word");
      txtSize.Text = _settings.GetSingleValue("size");
      rgb2.Text = _settings.GetSingleValue("color");
    }
  private static void BuildHeader()
  {
    // get a page handler
    System.Web.UI.Page pg = (System.Web.UI.Page)HttpContext.Current.CurrentHandler;

    // check if script already added to the page header
    foreach (Control ctl in pg.Header.Controls)
    {
      if (ctl.GetType() == typeof(HtmlGenericControl))
      {
        HtmlGenericControl gc = (HtmlGenericControl)ctl;
        if (gc.Attributes["src"] != null &amp;&amp; gc.Attributes["src"].Contains("color_functions.js"))
        {
          pg.Header.Controls.Remove(ctl);
        }
        if (gc.Attributes["src"] != null &amp;&amp; gc.Attributes["src"].Contains("js_color_picker_v2.js"))
        {
          pg.Header.Controls.Remove(ctl);
        }
        if (gc.Attributes["href"] != null &amp;&amp; gc.Attributes["href"].Contains("js_color_picker_v2.css"))
        {
          pg.Header.Controls.Remove(ctl);
        }
      }
    }
    HtmlGenericControl js = new HtmlGenericControl("script");
    js.Attributes.Add("type", "text/javascript");
    js.Attributes.Add("src", "../Example_05/color_functions.js");
    pg.Header.Controls.Add(js);
    HtmlGenericControl js2 = new HtmlGenericControl("script");
    js2.Attributes.Add("type", "text/javascript");
    js2.Attributes.Add("src", "../Example_05/js_color_picker_v2.js");
    pg.Header.Controls.Add(js2);
    HtmlGenericControl css = new HtmlGenericControl("link");
    css.Attributes.Add("rel", "stylesheet");
    css.Attributes.Add("type", "text/css");
    css.Attributes.Add("href", "../Example_05/js_color_picker_v2.css");
    pg.Header.Controls.Add(css);
  }

Extension itself pretty dumb – it runs on comment serving and decorates word with CSS style according to the size/color of your choosing. The important line is:

ExtensionManager.SetAdminPage("Example_05", "~/Example_05/Admin.aspx");

Here you tell BlogEngine to use your custom admin page instead default one, generated by Extension Manager. Everything else is as simple as it gets.

[Extension("Example_05", "1.0", "<a href=\"http://me.net\">Me</a>")]
public class Example_05
{
  static protected ExtensionSettings _settings = null;
  public Example_05()
  {
    Comment.Serving += new EventHandler<ServingEventArgs>(Post_CommentServing);
    InitSettings();
  }
  private static void Post_CommentServing(object sender, ServingEventArgs e)
  {
    string body = e.Body;
    string colored = "<span style=&#39;font-size:{0}px; color:{1}&#39;>{2}</span>";
    string word = _settings.GetSingleValue("word");
    string size = _settings.GetSingleValue("size");
    string color = _settings.GetSingleValue("color");
    if(word.Length > 0)
    {
      body = body.Replace(word, string.Format(colored, size, color, word));
    }
    e.Body = body;
  }
  protected void InitSettings()
  {
    ExtensionSettings settings = new ExtensionSettings("Example_05");
    settings.AddParameter("word");
    settings.AddParameter("size");
    settings.AddParameter("color");
    settings.AddValue("word", "BlogEngine");
    settings.AddValue("size", 12);
    settings.AddValue("color", "000000");
    settings.IsScalar = true;
    // set page that Extension Manager will use  
    // instead of default settings page
    ExtensionManager.SetAdminPage("Example_05", "~/Example_05/Admin.aspx");
    ExtensionManager.ImportSettings(settings);
    _settings = ExtensionManager.GetSettings("Example_05");
  }
}

ex_5-1_thumb.png If we've done everything correctly, we should be able to go to any post and, if it has word “BlogEngine” in it, this word will have size (in pixels) and color specified in our custom made admin page. You can always go to Admin/Settings select Example_05 extension from the list, change any values on the form and comments will reflect this change right away. As you can see, creating custom admin interface for extension in BlogEngine is definitely not a rocket science. All you need is make your hand-crafted page and let BlogEngine know about it – simple like that!

Download extension files here: example_05.zip

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.