Quickie Chalk extension for the tags issue

I mentioned in my previous blog post that the workaround I had for displaying the tags for a post vertically, rather than as a horizontal, comma-separated list, was flawed.

There are in fact two issues at play. First of all here's a magnified view of the tag list in Firefox 3.0:

image

As you can see, the biggest problem is that the clever CSS hackery I used means that the commas are still displayed in a line after the title, like an ellipsis with tails. At normal size this isn't really visible, but it's there nevertheless.

The second, bigger, issue is that in Chrome and Safari (they use the same rendering engine), the vertical tag list looks like this:

image

Which is just nasty. Now, I could just fiddle with the CSS again, but it's time to write a bit of C# and create a Chalk extension.

The basic idea is simple: write a class with one or more methods, decorate the class with ChalkAttribute, compile, and deploy.

I'll start off with the shell. Since I intend writing more "one-shot" Chalk methods, I'll arrange them all in a class called JmbChalk.

   1: using System;
   2: using System.Web;
   3: using Graffiti.Core;
   4:  
   5: namespace JmbChalk {
   6:   [Chalk("JmbChalk")]
   7:   public class JmbChalk {
   8:  
   9:     public string TagList(string tagList, string preTag, string postTag, string linkClass) {
  10:  
  11:       return string.Empty;
  12:     }
  13:   }
  14: }

From this you can see a couple of things in the boilerplate. First you must add Graffiti.Core as a reference and into the using list. It is this assembly that contains the ChalkAttribute class. I'm also adding System.Web because I'll be accessing a class there that will help me set up the url for each tag.

The Chalk method is called TagList. It takes four parameters: the taglist itself, some value before each tag (for example, <li> although it doesn't have to be an HTML element tag), some value after (for me, </li>) and then the class name to apply to the <a> element.

The method is pretty easy: split the taglist into individual tags, and then construct the HTML snippet for each tag, by concatenating everything together:

   1: public string TagList(string tagList, string preTag, string postTag, string linkClass) {
   2:   string result = string.Empty;
   3:  
   4:   if (string.IsNullOrEmpty(tagList)) 
   5:     return result;
   6:  
   7:   var separators = new char[]{',', ';'};
   8:   string[] tags = tagList.Split(separators, StringSplitOptions.RemoveEmptyEntries);
   9:   if (tags.Length == 0)
  10:     return result;
  11:  
  12:   string absolutePath = VirtualPathUtility.ToAbsolute("~/tags/");
  13:   string format = string.IsNullOrEmpty(linkClass) ? 
  14:     "{3}<a href=\"{0}{1}/\">{2}</a>{4}" :
  15:     "{3}<a class=\"linkClass\" href=\"{0}{1}/\">{2}</a>{4}";     
  16:   foreach (string tag in tags) {
  17:     string cleanUrl = Util.CleanForUrl(tag);
  18:     result += string.Format(format, absolutePath, cleanUrl, tag, preTag, postTag);
  19:   }
  20:   return result;
  21: }

As you can see the tags folder for Graffiti is off the root and called tags (so we need to calculate the absolute path for it), and the Util.CleanForUrl method is a utility function found in Graffiti.Core.

A quick compile, and then I added the JmbChalk dll to the /bin folder for the website.

The change to postheader.view was pretty simple after that:

   1: <li class="tags">
   2:     Tags:
   3:     <ul>
   4:     $JmbChalk.TagList($post.TagList, "<li>", "</li>", "taglink")
   5:     </ul>
   6: </li>

Once that was uploaded, I could remove the hackery from the CSS file and the tags list now renders the same across all browsers I test against (Firefox, IE7, Chrome, and Safari).

image

Loading similar posts...   Loading links to posts on similar topics...

No Responses

Feel free to add a comment...

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response