Sonntag, 08. Juni 2008, Christoph Ertl
A view weeks ago I created the list of categories for my blog. After a while I was wondering if a tag cloud wouldn't be more intuitive and more fancy. Of course it is.
So I started to create my first Umbraco package. But before creating the package the cloud itself must be implemented.
The Tag Cloud
To get an idea what a tag cloud is and what it's based on have a look at Wikipedia.
Algorithm
There are a lot of posts and notes about tag clouds and how to calculate the weight of the tags. After reading a lot of these articles and trying some solutions myself I kept these two posts in mind.
As a result I use an logarithmic algorithm which should be fast enough and the quality of the result should be ok. Most of the posts are talking about calculating the font size, but I just calculate the weight of the tag. The font size (or color) itself is provided using stylesheets which provides a very wide range of displaying the tag cloud.
Appearance
As already mentioned this package only calculates the weight. So the appearance can be set using stylesheets. In this context the color, font size and weight are interesting. To get a usable tag cloud some points must be considered:
- The different weights must be visual distinguishable.
- At least when moving the mouse over a tag it should get an underline to see what's the whole name of the tag (See "ASP.NET Dynamic Data").
- The tags should appear in alphabetical order which is done automatically.
Example of one tag cloud (6 weights) using different appearances. Just fonts, Just color and a combination where 3 font sizes and 6 colors are used.
The Package
The Umbraco package is a very simple package containing
- the dll with the calculation and rendering logic
- an xslt file called TagCloud.xslt (at least the link to the aspx page must be corrected in this file)
- a macro called TagCloud
Usage
As you can see in the XSLT file which is part of the package just call the Method RenderTags().
string RenderTags(XPathNodeIterator nodes, string propertyAlias, string entryPattern, int nrOfWeightRanges)
- nodes: The nodes containing the tags to count.
- propertyAlias: The alias of the dynamic property containing the tags. In the default installation of the blog package the alias is "categories".
- entryPattern: The pattern used for rendering the tag.
Sample: <a href="blog.aspx?filterBy={0}" class="tc{1}" title="{2}">{0}</a>
There are three placeholders available:- 0: The tag text (used for link text and the url)
- 1: The calculated weight (here used for setting the stylesheet class)
- 2: The amount of occurrence (here used for displaying as tooltip)
- nrOfWeightRanges: With this parameter you can set how many weight ranges should be used. Having the problem with the distinguishableness in mind this should be at most a value of 5 or 6.
To get the appearance working you have to add classes for each weight in the stylesheet according to the number of weight ranges.
a.tc1 { font-size:100%; text-decoration:none; }
a.tc2 { font-size:110%; text-decoration:none; }
a.tc1:hover, a.tc2:hover { text-decoration:underline; }
...
Download
You can download the TagCloud Package here.
Usage outside of Umbraco
This package is not restricted to be used within Umbraco. Just add a reference to TagCloud.dll into your project and use the TagCloudCalculator class.
// create an instance of the TagCloudCalculator class
// passing the nrOfWeightRanges as parameter
TagCloudCalculator cloud = new TagCloudCalculator(6);
foreach(string tag in myTags) {
cloud.Count(tag);
// use this call if you already know the count
// cloud.Count(tag, count);
}
string html = cloud.Render(@"<a href=""blog.aspx?filterBy={0}"" class=""tc{1}"">{0}</a>");

Is there a way to limit the amount of Tags to show, e.g. I have 50 tags but I only want to display 15?
Hi Daniel, at the moment there is no way to limit the tags. Which 15 would you like to display? - Highest occurance - Lowest occurance - Random Chris
Hi Chris, thank you for the answer. I would like to display the highest occurance 15 TAGs. Cheers
Hi Chris, have you got an answer for that issue? Could you provide the DLL source code for this improvements? Thanks!
I am not sure what the dynamic property is? Is this something I would have declared in my document type? And I assume this is built to use the Tag tables native to the umbraco DB? I have installed the package and it was successful, but I am not having success displaying in tags and runtime. My tags occur two levels down from the identified node, xslt isn't my strong suit but that doesn't look a problem. Thanks for any help.
I am not using this for a blog, rather just wanting to show all the tags (distinctly and weighted) that exist in my nodes.
Figured out the problem. I was calling the wrong doc type in the [@nodeTypeAlias = '
Hi Chris, Just tried out your package. It worked fine at the beginning. But now the call to the helper returns 1 item with class tc-2147483648 and the rest is tc1 .. I've been deleting pages. Is this a known problem? Please rply by mail. Thanks Jesper
Hi Chris, Using my xslt I am able to display the tags. But the style class is not applying dynamically. The call to the helper returns 1 item with class tc-2147483648 and the rest is tc1. Please help to fix this issue. Thank you.
@Jegan: It's a known bug which only appears if there are only two tags to calculate. I'm working on it.
Hi Chris, I Uninstalled the package and it went sucessfully. But I am getting the following error. Please help me to remove it completely. Error occured System.IO.FileNotFoundException: Could not load file or assembly 'file:///E:\Websites\Ekology\bin\TagCloud.dll' or one of its dependencies. The system cannot find the file specified. File name: 'file:///E:\Websites\Ekology\bin\TagCloud.dll' at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, StackCrawlMark& stackMark) at System.Reflection.Assembly.LoadFrom(String assemblyFile) at umbraco.macro.GetXsltExtensions() WRN: Assembly binding logging is turned OFF. To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1. Note: There is some performance penalty associated with assembly bind failure logging. To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
Hi Chris, I have fixed the above problem by removing the line *ext assembly="/bin/TagCloud" type="TagCloud.Helper" alias="TagCloud.Helper" /* from xsltExtensions.xml file which is inside C:\Inetpub\wwwroot\config folder. So, hope that removing the reference from the config file during the uninstallation process will help out Thank you
Hi Chris, Have you had chance to look at the bug that Jegan and Jasper mention - I have it too - if you would like any help tracking the bug down please let me know and maybe share the source code so that we could work togther?
An update is available for download. The "two tag" bug has been fixed. Have a look at http://www.christophertl.net/blog/2009/12/8/update-of-umbraco-tag-cloud-package.aspx
Hi Daniel, there's a way I found to display only N tags out of the total. You assign the result of rendertags to a variable, terminate the pattern string with a very special char (like § for example) and then you split on it, so you can count, sort, or do whatever you want with it. Hope it helps. (i tried to post some code snippets but didn't work...) Massimo