Nik's Technology Blog

Travels through programming, networks, and computers

Create a jQuery Tag Cloud from RSS XML Feed

I previously created a jQuery Blogger Template Category List Widget to retrieve blog categories from a Blogger.com RSS feed and create a list of links which click through to Blogger label pages.

I've now taken this code a step further and modified it to calculate the number of times each category/tag occurs enabling me to create a tag cloud from the data, like the one below.

 

Before I explain the code I wrote to make the tag cloud I'll go through the solution to a bug I found with the original categories code.

You may recall this snippet of code where I iterate through each post and then each category of each post, finally, when all the categories have been added to the array I sort them prior to de-duping them.

$.get('/blog/rss.xml', function(data) {
//Find each post
        $(data).find('item').each(function() {
//Get all the associated categories/tags for the post
            $($(this)).find('category').each(function() {
                categories[categories.length] = $(this).text();
            });
        });
        categories.sort();

I later refactored the code removing the $(data).find('item').each iteration which wasn't required since find('category') will find them all anyway.

I then discovered that the JavaScript .sort() function was case-sensitive which resulted in lower case categories being placed at the end of the list, causing problems when I de-dup them.

So the rewritten snippet of code became:

$.get('blog/rss.xml', function(data) {
     //Find each tag and add to an array
     $(data).find('category').each(function() {
         categories[categories.length] = $(this).text();
     });
     categories.sort(caseInsensitiveCompare);

where caseInsensitiveCompare refers to a JavaScript compare function:

function caseInsensitiveCompare(a, b) {
    var anew = a.toLowerCase();
    var bnew = b.toLowerCase();
    if (anew < bnew) return -1;
    if (anew > bnew) return 1;
    return 0;
}

Creating the Tag Cloud jQuery Code

I start off as before fetching the XML, adding all the categories/tags from the RSS feed to a JavaScript array, then sorting them.

But I needed a way to store, not only the tag name, but the number of times that tag is used on the blog (the number of times the category appears in the feed).  For this I decided to use a multi-dimensional array which would essentially store the data in a grid fashion e.g.

Tag Name Count
ASP.NET 5
Accessibility 2
Blogging 15
jQuery 2

 

The de-dup loop from my previous categories script now performs two jobs, it removes the tag duplicates and creates a count of each tag occurrence.

Once the multi-dimensional array has been populated, all that's left to do is iterate through the array creating the HTML necessary to build the tag cloud, followed by appending it to a DIV tag with an ID="bloggerCloud" on the page.

Note the calculation I perform to get the tags appearing a reasonable pixel size ((tagCount * 3) + 12).

$(document).ready(function() {
    var categories = new Array();
    var dedupedCategories = [];
    $.get('blog/rss.xml', function(data) {
        //Find each tag and add to an array
        $(data).find('category').each(function() {
            categories[categories.length] = $(this).text();
        });
        categories.sort(caseInsensitiveCompare);
        //Dedup tag list and create a multi-dimensional array to store 'tag' and 'tag count'
        var oldCategory = '';
        var x = 0;
        $(categories).each(function() {
            if (this.toString() != oldCategory) {
                //Create a new array to put inside the array row 
                dedupedCategories[x] = [];
                //Store the tag name first 
                dedupedCategories[x][0] = this.toString();
                //Start the tag count 
                dedupedCategories[x][1] = 1;
                x++;
            } else {
                //Increment tag count
                dedupedCategories[x - 1][1] = dedupedCategories[x - 1][1] + 1;
            }
            oldCategory = this.toString();
        });
        // Loop through all unique tags and write the cloud
        var cloudHtml = "";
        $(dedupedCategories).each(function(i) {
            cloudHtml += "<a href=\"/blog/labels/";
            cloudHtml += dedupedCategories[i][0] + ".html\"><span style=\"font-size:" + ((dedupedCategories[i][1] * 3) + 12) + "px;\">";
            cloudHtml += dedupedCategories[i][0] + "</span></a> \n";
        });
        $('#bloggerCloud').append(cloudHtml);
    });
    return false;
});

Since building this script I've now gone one step further and created a jQuery plug-in based on this code.  For more details and the source code see my jQuery Blogger.com Tag Cloud Plugin page.

Setting Up ASP.NET MVC with NUnit for Visual Studio 2008 Standard Edition &amp; Visual Web Developer Express 2008

I've just spent my lunch hour downloading and installing ASP.NET MVC.  I also downloaded the sample chapter from Professional ASP.NET MVC 1.0 (large PDF) which walks through the development of NerdDinner.com.  I began to create a test ASP.NET MVC project on Visual Studio 2008 Standard.

One of the main positives of ASP.NET MVC is that Test Driven Development is so much easier than with ASP.NET Webforms.

I soon realised when I created my first ASP.NET MVC project however that unless you have Visual Studio Professional or higher you don't get Visual Studio test Unit Framework, which means that to create a test project, you first need to install another testing framework such as NUnit, and configure Visual Studio or Visual Web Developer 2008 to use it.

This is an extract from the book Professional ASP.NET MVC 1.0:

Note: The Visual Studio Unit Test Framework is only available with Visual Studio 2008 Professional and
higher versions). If you are using VS 2008 Standard Edition or Visual Web Developer 2008 Express you
will need to download and install the NUnit, MBUnit or XUnit extensions for ASP.NET MVC in order for
this dialog to be shown. The dialog will not display if there aren't any test frameworks installed.

I already had NUnit installed, so I began my search for an NUnit extension for ASP.NET MVC, which I found here. Updated NUnit Templates for ASP.Net MVC 1.0 RTM

After running installNUnit.cmd which created the registry entries required by Visual Studio, you need to make sure the registry entries created point to the compressed templates.

Note: If you are using Visual Web Developer 2008, this might be all you need to do.  Click on File > New Project and check to see if "Test" appears under "Project types" on the left-hand menu in the dialogue box.  If not carry on reading.

Copy the NUnit test templates from the downloaded directory (in your chosen .NET language) MvcApplication.NUnit.Tests.zip to the following folder on your machine:

%Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Test

or here for VWD 2008:

%Program Files%\Microsoft Visual Studio 9.0\Common7\IDE\VWDExpress\ProjectTemplates\CSharp\Test

Then make sure the registry entry here:

HKEY_LOCAL_MACHINE\SOFTWARE\VisualStudio\9.0\MVC\TestProjectTemplates\NUnit\C#

or here for VWD 2008:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VWDExpress\9.0\MVC\TestProjectTemplates\NUnit\C#

Correctly points to the location of MvcApplication.NUnit.Tests.zip. e.g.

Path: CSharp\Test\

Template: MvcApplication.NUnit.Tests.zip

Then close all instances of Visual Studio and open up the command prompt and move to the following location:

C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE>

and run the following command:

> devenv /setup

Once this has completed, you should find that when you create an ASP.NET MVC project, you will now get another pop-up menu asking you if you wish to create a unit test project for your application using NUnit.

jQuery Blogger Template Category List Widget

Blogger is a hosted blogging service which allows you to publish your blog to your own URL and create your own custom HTML templates to match your website design. 
I have been using Blogger for this blog for several years, and have been trying to find a good way of displaying a list of categories on each blog page.

As yet I haven't found an official way of creating a category list using the Blogger mark-up code, so I decided to write my own widget to do the job for me.

When I say category list I mean a list of all the blog tags/labels in your blog, each linking to a page with posts categorised using that particular tag, just like the examples below.

Blog Categories

Because Blogger is a hosted blogging service you can't use a server-side language to create the category list for your HTML template, instead you must rely on client-side JavaScript.

Thankfully the Blogger service publishes XML files to your website along with the post, archive and category HTML pages.  These are in ATOM and RSS formats and are there primarily for syndication, but XML files are also fairly straight-forward to parse using most programming languages and contain all the category data we need to build a categories list.

I chose to use the jQuery library because it makes the process even easier.

The Blogger XML Format

From the Blogger ATOM XML snippet below you can see that each blog item can have multiple category nodes.  This means that the code must loop through each blog post, then loop through each category of each post to create our category list, but it also means that we will have duplicate categories, because more than one post can have the same category.

<item>
  <guid isPermaLink='false'></guid>
  <pubDate>Thu, 14 May 2009 18:30:00 +0000</pubDate>
  <atom:updated>2009-05-15T11:35:03.262+01:00</atom:updated>
  <category domain='http://www.blogger.com/atom/ns#'>C Sharp</category>
  <category domain='
http://www.blogger.com/atom/ns#'>ASP.NET</category>
  <category domain='
http://www.blogger.com/atom/ns#'>Visual Studio</category>
  <title>Language Interoperability in the .NET Framework</title>
  <atom:summary type='text'>.NET is a powerful framework which was built to allow cross-language support...</atom:summary>
  <link>http://www.nikmakris.com/blog/2009/05/language-interoperability-in-net.html</link>
  <author>Nik</author>
  <thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total>
</item>

The jQuery Code

The jQuery code is fairly easy to follow, but here is a quick explanation.  After the DOM is available for use, I create two JavaScript arrays, one to hold the categories and one to hold our de-duped category list.  Then I load in the Blogger RSS feed and iterate through each blog post adding each category to the categories array.
Once it reaches the end of the RSS feed, I need to sort the array into alphabetical order so that I can de-duplicate the categories list I just populated, which is what the next jQuery .each() function does.
All I have left to do is loop through the de-duped categories list, create the HTML link for each category and the append the HTML unordered list to the page.

$(document).ready(function() {
    var categories = new Array();
    var dedupedCategories = new Array();
    $.get('/blog/rss.xml', function(data) {
        //Find each post
        $(data).find('item').each(function() {
            //Get all the associated categories/tags for the post
            $($(this)).find('category').each(function() {
                categories[categories.length] = $(this).text();
            });
        });
        categories.sort();
        //Dedup category/tag list
        var oldCategory = '';
        $(categories).each(function() {
            if (this.toString() != oldCategory) {
                //Add new category/tag
                dedupedCategories[dedupedCategories.length] = this.toString();
            }
            oldCategory = this.toString();
        });
        // Loop through all unique categories/tags and write a link for each
        var html = "<h3>Categories</h3>";
        html += "<ul class=\"niceList\">";
        $(dedupedCategories).each(function() {
            html += "<li><a href=\"/blog/labels/";
            html += this.toString() + ".html\">";
            html += this.toString() + "</a></li>\n";

        });
        html += "</ul>";
        $('#bloggerCategories').append(html);
    });
    return false;
});

 

Update your Blogger Template HTML to Show Categories

The only HTML you need to add to your Blogger template is a call to jQuery, and this script in the head of your page, plus an empty HTML DIV tag, in the place where you want your categories list to appear.

<script type="text/javascript" src="/scripts/jquery.js"></script>
<script type="text/javascript" src="/scripts/blogcategories.js"></script>

<div id="bloggerCategories"></div>

You can see the script in action on my blog, or see this code rewritten to create a tag cloud.

An Introduction to Web Development and Design for Work Experience Students

We have a school student coming into our agency for work experience shortly, so I'm putting together a programme which will introduce him to the various areas of web development, such as HTML, CSS, client-side and server-side code, databases and XML.

It is going to be difficult to cover the various different skills involved in web development in a week, and without knowing what sort of web development knowledge the student already possesses it is hard to determine what can be achieved in such a short time.

However the main goal of work experience is to give the student a flavour of what is involved in the profession, to allow them to make an informed decision on whether such a career is for them.

I've structured the programme as follows:

Day 1 - Introduction to Web Design
Day 2 - Introduction to HTML and CSS
Day 3 - Understanding web servers, web browsers and HTTP and FTP
Day 4 - Introduction to server-side and client-side programming
Day 5 - Overview of databases and XML

Within each topic I have posed questions and tasks, which will require research and learning.  For each subject I have provided links to tutorials and online information.

I'm also aware that web development is very much a practical and creative skill, so I've also set a project which will run for the whole week and will allow him to put what he has learned into practice by building a simple personal portfolio website.

I have no idea whether I'm being too ambitious, but surely that will depend on the student's current knowledge and interest in the subject.  I think that it can easily be tailored to each student depending on their interests. 

I have uploaded a PDF of my programme entitled An Introduction to Web Development and Design for Work Experience Students and would appreciate any feedback.

Language Interoperability in the .NET Framework

.NET is a powerful framework which was built to allow cross-language support.  All .NET code is compiled to Intermediate Language (IL) whether you are developing in C#, VB.NET, J# or any other .NET language.  This means it is possible to build applications with modules written in different languages, because when the application is compiled it will all be compiled to a common language, IL.

This means a class written in one language can inherit from a class written in another language, or an object can directly call a method of another class written in another .NET language.  Visual Studio also allows you to step through all the different modules in the debugger.

To demonstrate the Language Interoperability in .NET, I'm going to call a VB.NET method from the code-behind page of a C# ASP.NET page.  This isn't something you would ordinarily want to do, but its an easy way to show the power of .NET.

In Visual Studio, right-click your website root in Solution Explorer and select add reference.  Scroll down the .NET tab until you find Microsoft.VisualBasic and click ok.

This will modify your Web.Config file by adding an assembly reference to Microsoft.VisualBasic to the assemblies list.

            <assemblies>
                <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
                <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="System.Web.Extensions.Design, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
                <add assembly="System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
                <add assembly="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
                <add assembly="Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
      </assemblies>

To use the VB.NET language within your C# webform you need to add a using Microsoft.VisualBasic; statement at the top of your code-behind page.

In my demo example below I am going to use the VB.NET MonthName method of DateAndTime to get the current month's name and display it on my page using a ASP.NET label control.  The bold code below is VB.NET interspersed with C#.

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.VisualBasic;

public partial class language_interop : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        int month = DateTime.Today.Month;
        string monthName = DateAndTime.MonthName(month, false);
        labelMonthName.Text = monthName;
    }
}

Does your PC Keeping Forgetting the Date & Time?

Yesterday my aging desktop PC decided not to boot, and instead displayed this helpful error "CMOS Checksum Error".
In order to get it to boot into Windows I had to press Delete to go into the BIOS settings and change the configuration from "Halt on all errors" to "halt on no errors".  Upon saving the BIOS settings and restarting the error disappeared.

Sometimes though a PC with a dead CMOS battery will boot as normal but forget the date and time on each reboot.  This can lead to odd effects.  For instance I tried to logging into my webmail only to be told the SSL licence wasn't valid, not because it had expired but because my computer thought it was 2001!

CMOS Battery at Fault

Once I got into Windows I got a few "Windows has found new hardware" messages and my system clock had reverted to a day in 2001.
As soon as I saw my clock had forgotten the time and the date, all evidence pointed towards the CMOS battery being at fault.  Its funny how a simple little battery that most people don't even realise existed inside their PC can bring a computer to its knees.

Locating & Changing the CMOS Battery

In a desktop PC the CMOS battery is fairly straight forward to find.  They normally look like a large wrist watch battery, with CR2032 lithium batteries being the most common.  A simple search on eBay will find you a cheap replacement.  Just be careful removing and fitting anything on a motherboard, because any static electricity on your body could fry delicate computer chips.

CMOS battery on a desktop PC motherboard

On a laptop or notebook they are more difficult to find and generally more expensive.  On my Dell Inspiron you need to lift out the main battery and pull out a small flap to locate the CMOS battery.

Dell laptop battery housing

Location of CMOS battery in Dell Inspiron laptop

Dell Inspiron CMOS battery location

My Dell just so happens to take a 7.2V 15mAh Ni-MH CMOS battery, which again, performing a quick search on eBay will find you a replacement.

Fitting the new battery in either case is very straight forward.

Read more about Installing a CMOS Battery here.