Generating tagclouds is nothing new. People have been generating
tagclouds server-side since the seventies. Lately more and more tagclouds are being generated client-side.
There is nothing wrong with generating tagclouds server-side. Telerik has a great
tagcloud server control. Generating tagclouds server-side can bring some overhead though, so depending on the scenario and the requirements you might decide to do it client-side. There are a ton of fancy ready-to-use jQuery
tagcloud plug-ins out there. None of them met my requirements perfectly, so I decided to do it myself.
In this post you can find my own implementation. It's simple, straightforward and a decent base to start experimenting yourself.
Making the tags available through an ASMX WebserviceIn my implementation I use an ASMX Webservice to expose a TagCollection. The TagCollection is an object which contains a List<Tag>. The TagCollection also has a MaxWeight property which we will need on the client-side to calculate the relative weight.
1: public class TagCollection { 2: public TagCollection() { } 3:
4: public TagCollection(List<Tag> items, int maxWeight) { 5: this.Items = items;
6: this.MaxWeight = maxWeight;
7: }
8:
9: public List<Tag> Items { get; set; } 10: public int MaxWeight { get; set; } 11: }
A Tag is a simple object with two properties: Value and Weight.
1: public class Tag { 2: public Tag() { } 3:
4: public Tag(string value, int weight) { 5: this.Value = value;
6: this.Weight = weight;
7: }
8:
9: public string Value { get; set; } 10: public int Weight { get; set; } 11: }
In the ASMX WebService I created the GetTagCollection method which returns a TagCollection. Don't forget to uncomment the
[System.Web.Script.Services.ScriptService] declaration and to add the
[ScriptMethod(ResponseFormat = ResponseFormat.Json)] declaration to the GetTagCollection method.
1: [WebService(Namespace = "http://TagCloudWithJquery.com")]
2: [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
3: [System.Web.Script.Services.ScriptService]
4: public class TagService : System.Web.Services.WebService { 5: [WebMethod]
6: [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
7: public TagCollection GetTagCollection() { 8: var items = new List<Tag>() { 9: new Tag(".NET", 20), 10: new Tag("CodeSnippets", 15), 11: new Tag("...", 10), 12: new Tag("ASP.NET", 18) 13: };
14: var maximumWeight = items.Max(i => i.Weight);
15:
16: var tagCollection = new TagCollection(items, maximumWeight);
17:
18: return tagCollection;
19: }
20: }
Consuming the ASMX WebserviceConsuming the ASMX Webservice with jQuery is relatively simple. If you are new to consuming ASMX Webservices with jQuery, I advice you to read
this excellent article.
When the document is ready I make a call to the ASMX Webservice and when the call is successful all the work gets passed to the onTagCloudSuccess function.
1: $(document).ready(setupTagCloud);
2:
3: function setupTagCloud() { 4: $.ajax({ 5: type: "POST",
6: contentType: "application/json; charset=utf-8",
7: url: "Services/TagService.asmx/GetTagCollection",
8: data: "{}", 9: dataType: "json",
10: success: onTagCloudSuccess
11: });
12: }
Don't forget to add a script reference to
the latest version of jQuery.
Generating the tagcloudAll the work happens in the onTagCloudSuccess function. In this function I iterate over all the items in the TagCollection. For each item I calculate its relative weight using the TagCollections MaxWeight property. Depending on the relative weight the tag gets a different css class. This logic can be found in the getCloudItemClass function.
Finally I append a new listitem to the unordered list 'items' using the tags value and the calculated css class.
1: function onTagCloudSuccess(data, textStatus) { 2: var maxWeight = data.d.MaxWeight;
3:
4: $.each(data.d.Items, function(i, item) { 5: var itemWeight = item.Weight;
6: var relativeItemWeight = itemWeight / maxWeight;
7: var itemClass = getCloudItemClass(relativeItemWeight);
8:
9: $("#items").append("<li class='" + itemClass + "'>" + item.Value + "</li>"); 10: });
11: }
12:
13: function getCloudItemClass(weight) { 14: if (weight < 0.35) { 15: return "light";
16: } else if (weight < 0.7) { 17: return "medium";
18: } else { 19: return "heavy";
20: }
21: }
Don't forget to add an unordered list with the id set to 'items' to your page.
So far this looks something like this.

I used following css to make the unordered list look like a tagcloud.
1: #items li { 2: display: inline-block;
3: margin: 4px;
4: }
5:
6: .heavy { font-size: 60px ; color:Red; } 7: .medium { font-size: 30px; color:Orange; } 8: .light { font-size: 14px ; color:Yellow; }Setting the display to inline-block on the listitems makes the unordered list go horizontal instead of vertical. The heavy, medium and light classes are used to give the tagclouditems a style that matches with their heaviness.
The final result looks like this.

Different ways of marking up a tagcloud can be found in
this article.
Get the sourceYou can find the full source
here.
FeedbackAs always I want to hear your feedback. Please tell me how this implementation can be improved.