When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles [1.x] [2.0]
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
Headlines from ASPWire.com
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article
Jobs
















internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers
ASP ASP.NET ASP FAQs Message Board Feedback ASP Jobs
Print this Page!

Windows Systems Administrator
Jupitermedia
US-CT-Darien

Justtechjobs.com Post A Job | Post A Resume

Published: Wednesday, October 25, 2006

Creating a Tag Cloud in ASP.NET
By Scott Mitchell


Introduction
A tag cloud is a way to display a weighted list such that the weight of each item is reflected by the size of the item's text. Tag clouds provide a quick way for one to eyeball a list and ascertain what items are more prevalent. Oftentimes, each item in a tag cloud is rendered as a link that, when clicked, allows the user to drill into the selected category. For example, given any parent/child relationship in a database, we may be interested in seeing how many children each parent has, relative to one another. The following image of a tag cloud lists the categories in the Northwind database, with the size of each item is proportional to the number of products for each category, relative to the other categories. (Each category name, if clicked, takes the user to a page that lists the products for that particular category.)

A tag cloud.

Tag clouds are commonly used in websites that support tagging. Tagging is a technique of assigning a set of string values to a particular item - such as classifying a picture of your pet dog at a photo sharing website with string tags like "dog", "pet", "adorable", and so on. Tags provide an informal way for users to easily classify content and make it easy to visualize the most common tags and to drill down into a specific tag. However, tag clouds are not limited to websites that support tagging and can be used to offer an alternative view of a weighted list (such as parent/child data in a database).

In this article we'll examine how to build a tag cloud in ASP.NET. In this article we'll focus on accomplishing this through code in an ASP.NET page's code-behind class. In a future article, we'll move this code out of the ASP.NET page and into a stand alone, custom, compiled server control that supports data binding, use of declarative data source controls, and so on. Read on to learn more!

- continued -

Deciding on the Tag Cloud's Font Sizing
When designing a tag cloud, it is important to first determine how the font sizes will vary by item. The font sizes can be specified using relative font sizes - xx-small, medium, x-large, and so on - or by absolute font sizes - 12pt, 32pt, etc. The benefit of using relative font sizes is that the fonts will scale based on a user's browser's text size settings. Another design decision to make is the spectrum of font sizes. That is, how many distinct font sizes are allowed? For the code we'll examine shortly, I've decided to use seven absolute font sizes: xx-small, x-small, small, medium, large, x-large, xx-large.

Another vital design decision is how the font sizing is selected based on the distribution of the weights. For my code, I've decided to use a simple linear distribution. If the weighted list ranges from a minimum value of, say, 60, to a maximum value of 200, then I break down each of the seven font sizes into ranges plotted linearly along the minima and maxima. In this example, the delta is 140 (200 - 60). Divided by 7 results in each font size having a range of 20 units. So for any list items whose weight is between 60 and 80, I use font size xx-small; for those between 80 and 100, I use x-small; and so on.

While this linear scale is simple to implement and works well for evenly distributed data points, if you have skewed data points you'll end up with potentially extreme results. Consider the case where the weighted list being displayed has one data point with a weight of 60 (our minimum) and five data points between weights 180 and 200. The result is that the first data point will be displayed with the smallest font size (xx-small) and all remaining five will be displayed in the largest font size (xx-large). But this doesn't show the variation between the five in the 180-200 range. To capture this, an alternative model is to base the font sizes on the standard deviation of the distribution, which captures how far each data point deviates from the mean (the average). For more on this, check out Cloud Control for ASP.NET. It's an open source tag cloud control for ASP.NET created by Rama Krishna Vavilala that uses the standard deviation model.

Building the Cloud
Ideally, a tag cloud could be associated with some data, a few properties set, and, voila, the tag cloud appears! In fact, we'll examine how to accomplish exactly this in a future article by creating a custom, compiled ASP.NET 2.0 server control. For now, though, let's just implement the tag cloud directly from an ASP.NET page (although this could be moved to a User Control for greater reuse opportunities).

First things first - we need the data that returns the list with each item weighted. In the demo downloadable at the end of this article, I have used a SqlDataSource control to query the Northwind database, returning the CategoryID, CategoryName, and number of products belonging to each category:

SELECT Categories.CategoryID, Categories.CategoryName, 
       COUNT(Products.ProductID) AS NumberOfProducts 

FROM Categories 
    INNER JOIN Products ON 
        Categories.CategoryID = Products.CategoryID 

GROUP BY Categories.CategoryID, Categories.CategoryName
ORDER BY Categories.CategoryName

This query uses the GROUP BY clause to return the count of products associated with each category. See Using the GROUP BY Clause for more information on this SQL clause.

The tag cloud is outputted in the Web page via a Literal Web control named CloudMarkup. In code we're going to loop through the database results, compute the font size scale, and then emit an HTML hyperlink as markup into the Text property of the Literal control. To start, we need to get the data from the SqlDataSource control. This is accomplished by calling its Select() method, which returns a DataView object:

'First, read data from SqlDataSource
Dim cloudData As DataView = CType(CategoriesProductsBreakdownDataSource.Select(DataSourceSelectArguments.Empty), DataView)

Next, a series of constants are defined in an attempt to generalize this code at least a little bit. For example, there are constants that define the names of the database columns that return the weight, the text field to display, along with the field to use (and a format string) when constructing the URL for each hyperlink. You'll also find the set of font sizes and the markup to inject between each link.

Const SpacerMarkup As String = " " 'The markup injected between each item in the cloud
Dim FontScale() As String = {"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"}

'All database column names are centralized here. To customize this, simply modify the column names here
Const WeightColumnName As String = "NumberOfProducts"
Const TextColumnName As String = "CategoryName"
Const NavigateUrlColumnName As String = "CategoryID"
Const NavigateUrlFormatString As String = "~/ViewProductsByCategory.aspx?CategoryID={0}"

Next, we need to determine the minimum and maximum weight values in the list. This information is then used to compute the linear scale by which we'll map an item's weight to a font size. The scaleUnitLength holds the "length" of each notch on the scale.

Dim minWeight As Decimal = Decimal.MaxValue, maxWeight As Decimal = Decimal.MinValue

For Each row As DataRowView In cloudData
    Dim numProductsObj As Object = row(WeightColumnName)
    If Not Convert.IsDBNull(numProductsObj) Then
       Dim numProductsDec As Decimal = Convert.ToDecimal(numProductsObj)

       If numProductsDec < minWeight Then minWeight = numProductsDec
       If numProductsDec > maxWeight Then maxWeight = numProductsDec
    End If
Next

Dim scaleUnitLength As Decimal = (maxWeight - minWeight + 1) / Convert.ToDecimal(FontScale.Length)

After computing the scale, the data is enumerated one more time, this time with a hyperlink (<a>) element emitted for each record. To find the place on the scale, the current item's weight is subtracted from the minimum and divided by scaleUnitLength. This index is used to select the appropriate font size from FontScale. Also note that the specified values for NavigateUrlColumnName and NavigateUrlFormatString are used to configure the href portion of the hyperlink.

For Each row As DataRowView In cloudData
    Dim numProductsObj As Object = row("NumberOfProducts")
    If Not Convert.IsDBNull(numProductsObj) Then
       Dim numProductsDec As Decimal = Convert.ToDecimal(numProductsObj)

       Dim scaleValue As Integer = Math.Truncate((numProductsDec - minWeight) / scaleUnitLength)
       CloudMarkup.Text &= String.Format("<a href=""{0}"" style=""font-size:{1};"">{2}</a>{3}", _
                                    Page.ResolveUrl(String.Format(NavigateUrlFormatString, row(NavigateUrlColumnName).ToString())), _
                                    FontScale(scaleValue), row(TextColumnName).ToString(), SpacerMarkup)
    End If
Next

That's all there is to it! The resulting output is a chunk of HTML that, when rendered in the user's browser, lists each category as a hyperlink pointing to ViewProductsByCategory.aspx?CategoryID=categoryID. Each link's text size is based on its weight using a linear scale. The following screenshot below shows a tag cloud of the Northwind database's categories table along with the raw data used to populate the cloud.

A tag cloud along with the raw data.

Conclusion
Tag clouds can provide an alternative means for displaying a weighted list. As we saw in this article, they can be implemented with just a bit of code (although the standard deviation approach takes a bit more effort), and offer visual cues and a way to quickly drill into the details of any item. In a future article we'll look at how to move this logic to a custom, compiled ASP.NET 2.0 server control. Until then.....

Happy Programming!

  • By Scott Mitchell


    Attachments

  • Download the code used in this article


    Windows Internet Technology | ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article



  • JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

    Solutions
    Whitepapers and eBooks
    Microsoft Article: Will Hyper-V Make VMware This Decade's Netscape?
    Microsoft Article: 7.0, Microsoft's Lucky Version?
    Microsoft Article: Hyper-V--The Killer Feature in Windows Server 2008
    Avaya Article: How to Feed Data into the Avaya Event Processor
    Microsoft Article: Install What You Need with Windows Server 2008
    HP eBook: Putting the Green into IT
    Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
    Avaya Article: Setting Up a SIP A/S Development Environment
    IBM Article: How Cool Is Your Data Center?
    Microsoft Article: Managing Virtual Machines with Microsoft System Center
    HP eBook: Storage Networking , Part 1
    Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
    MORE WHITEPAPERS, EBOOKS, AND ARTICLES
    Webcasts
    Intel Video: Are Multi-core Processors Here to Stay?
    On-Demand Webcast: Five Virtualization Trends to Watch
    HP Video: Page Cost Calculator
    Intel Video: APIs for Parallel Programming
    HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
    Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
    MORE WEBCASTS, PODCASTS, AND VIDEOS
    Downloads and eKits
    Sun Download: Solaris 8 Migration Assistant
    Sybase Download: SQL Anywhere Developer Edition
    Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
    Red Gate Download: SQL Compare Pro 6
    Iron Speed Designer Application Generator
    MORE DOWNLOADS, EKITS, AND FREE TRIALS
    Tutorials and Demos
    How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
    eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
    IBM Article: Collaborating in the High-Performance Workplace
    HP Demo: StorageWorks EVA4400
    Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
    Microsoft How-to Article: Get Going with Silverlight and Windows Live
    MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES