Creating Web Articles
Sunday, September 4, 2005
Today, I'll give a little insight into how I create my web site articles, Journal entries mainly, using WebEdit.NET. The focus is on template-based editing, with the help of the code interpreter.
I have a template like this:
<html> <head> <!-- $clearTemplateParams()% --> <!-- $getTemplateFileBase()% --> <title>$getTemplateTitle()%</title> </head> <body bgcolor="white"> <h1>$getTemplateTitle()%</h1> <p style="text-align: right;"> $getTemplateDateText()% </p> <p> Article goes here ... </p> </body> </html>
WebEdit.NET, when it opens a file like this as a template, prompts me with the parameter dialog, into which I can enter strings. However, wouldn't it be a little easier if I had a custom dialog that:
- Allows me to select the article publication date with a calender control?
- Presets the file name in accordance with the article publication date?
So, I wrote a little dialog function and assorted helpers in WebEdit's code interpreter. Here's the code:
clearTemplateParams() { sName = "TemplateParams"; if(Vars.ExistsValue(sName)){ Vars.RemoveValue(sName); } "OK"; } getTemplateTitle() { getTemplateParams().GetProperty("Title") } getTemplateDateText() { getTemplateParams().GetProperty("DateText") } getTemplateFileBase() { getTemplateParams().GetProperty("FileBase") } getTemplateParams() { ret = null; sName = "TemplateParams"; if(Vars.ExistsValue(sName)){ ret = Vars.GetValue(sName); }else{ sCaption = "Blog Entry Paramters"; sDescription = "Choose title, publication date, and file base:"; frm = new Gregor.UICore.Dialogs.FMultiInput(sCaption, sDescription); txtTitle = frm.AddTextBox(string.Empty); mc = frm.AddMonthCalendar(DateTime.Now); txtFileBase = frm.AddTextBox(DateTime.Now.ToString("yyyyMMdd")); handleDateChanged(sender, e){ txtFileBase.Text = mc.SelectionStart.ToString("yyyyMMdd"); } UserHandler.Add(mc, "DateChanged", handleDateChanged); if(frm.ShowDialog(WebEditApp.MainForm).Equals(DialogResult.OK)){ ToString(){ string.Concat("TemplateParams for: ", this.GetProperty("Title")); } ret = UserObject.Create(ToString); ret.AddProperty("Title", txtTitle.Text); pubDate = mc.SelectionStart; cult = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); ret.AddProperty("DateText", pubDate.ToString("dddd, MMMM d, yyyy", cult)); ret.AddProperty("FileBase", txtFileBase.Text); Vars.SetValue(sName, ret); } UserHandler.Remove(mc, "DateChanged", handleDateChanged); } ret; }
The whole architecture (cough!) has the following features:
- Since the template mechanism needs to evaluate several expressions, but I only want one dialog to pop up once, the dialog function returns its results as a complex object, saved explicitly in global scope.
- The clearTemplateParams() functions remove that object from cache. It is called at the beginning (see the first HTML comment in the template). It returns a dummy string ("OK"), since it is being commented out anyway. This helps avoiding the parameter dialog, which is still available both as a fallback for and as a second check on code-interpreter-supplied parameter values (depending on the "Avoid Parameter Dialog" setting in the "Token Expansion" settings group).
- The dialog is based on the FMultiInput class in Gregor.UICore.Dialogs, which can host any control, and offers a few convenient shortcuts for standard controls. Here, text boxes and the month calendar controls are used.
- There is an event handler - implemented as a nested routine - which updates the text box used for the file name base whenever the date in the MonthCalendar control changes. I use the file name as a means of filtering pre-recorded, future Journal entries from the Journal page and my RSS feed.
- The "Parameters used for file name bases" setting in the "Token Expansion" settings group lists the getTemplateFileBase() expression, so WebEdit knows where the file name base will come from (the file extension is copied from the template file automatically).
- For diagnostic purposes, the User Object that groups the template parameters has a ToString method. Note that User Object methods may be nested within the object's creation function (as is the case here), but they do not capture outer locals after the outer function returns.
To use the template, follow these steps:
- Save the HTML from above to a file.
- Paste the code from above into an editor window, and execute "code:Vars.Eval(Vars.Text)" in the Console tool window.
- In the "Token Expansion" settings group, check the "Avoid Parameter Dialog" setting, and prepend the string getTemplateFileBase() to the "Parameters used for file name bases" setting, followed by a semicolon, like this.
- Choose "File"/"Template"/"Open Template (Local) ..." to select the file. This dialog, should pop up now.
- When you save the file, the right file name, should be preset.