Implementing A Tag Cloud In The Lotus Notes ClientWelcome back. It's been awhile. I'd ask you why you haven't visited or called lately, but I know...it's me. I haven't been giving much to this relationship lately. I'll try harder...I promise. How about starting with a new post about creating a tag cloud in a Lotus Notes client application? That sounds good? Great...thanks for giving me a second chance! :-)
Way back at Lotusphere 2009, Nathan and I delivered a presentation on Web 2.0 design patterns for Lotus Notes. He focused on the web side of things (with XPages) and I worked on the client UI side. Unfortunately, some technical difficulties got in our way and the session wasn't nearly as good as it could have been. However, the content is still worth digging into, so I thought I'd start out with one that is useful for injecting the idea of topic popularity into your application: The Tag Cloud.
I'd guess that most people have at least seen a tag cloud by now, given that it is a pretty common Web 2.0 pattern. A tag cloud is used as a navigation mechanism to allow users to browse information and see at a glance what content is most popular or prevalent in an application. A tag cloud is simply a list of tags (be they user added or generated from categories) where the physical size of the tag represents the weight (frequency) of that information within the application. An important aspect of the tag cloud is that you can click on a tag and this action will filter the data list to show only the content with that tag. Here's an example from one of the Lotus products, Lotus Connections:
Tag clouds can be very useful in situations when a user wants to discover information rather than search for it. I've gone on and on before about the fact that most business applications are such that a user has a targeted objective when they use the app, so the UI should be designed to facilitate getting them to the info they need as quickly as possible. There are certain classes of applications, however, where browsing of information is more meaningful. A discussion database is a great example of this, as are apps such as product reviews, policies and procedures and so on. When discoverability will add value to your application, then a tag cloud might be a good choice for a UI component.
Before we jump into the implementation, let me put forth a few caveats. First, when I was initially coming up with this, I went through about four different methods of creating a tag cloud. These methods ranged from quite simple (like I'll be showing you here) to insane hackery. While it's pretty easy to build a tag cloud on the web and there are tons of code samples to do so, it was a bit of a challenge to implement one in the Notes client. Each of the different techniques I tried had strengths and weaknesses. I decided to go with the method shown below because it was the most straightforward and will work in R6 and above, so it's not limited to the latest and greatest version of Notes. It's not elegant, but it works. I'm a fan of clean, elegant design, but sometimes it's necessary to create something less than beautiful behind the scenes to make the end user experience better. As long as you are not creating a maintenance nightmare, I think it is OK that we work harder so our users don't have to.
The way I approached this technique was to make use of the category field in an existing Notes database. Exposing existing categories as a tag cloud is a very easy way to get started and introduce this functionality to your users. Personally, I find that tag clouds work best when the number of entries is not overwhelming. They do take up a lot of valuable screen real estate, so you'll need to make the call as to whether they add enough value to justify use or not. Of course, the ideas presented here can be applied to any data captured in a discrete field on your documents.
The first step in building the tag cloud component for the Notes client is to create the view that will be used to get the tags (categories). Here's a screenshot showing the view in my demo database.
The first column includes the count of all the tags in that grouping, which I find useful to display along with the tag cloud in some cases. We'll use this view to lookup the tags and display them in the tag cloud.
The next thing we need is to create the form that will serve as a container for the tag cloud. I decided to use a form as it gives the flexibility of having the tag cloud generated on the fly or via a process such as a scheduled agent. I'm also trying to make these techniques easy for newer developers, so the form and field idea works pretty well. Because we need the tags to be clickable, we need some sort of hotspot on each one. This could be likely by accomplished by using Lotusscript or a third-party product like Midas to build the tags in a rich text field and then put links around them but this seemed a little complex for my tastes. Thus, I decided to implement the tag cloud as a series of fields. Each field holds a single tag and then I created an action hotspot around each field. Let's break it down bit by bit:
First, the top of the form houses some computed fields that are used to lookup the tags and the quantity each of the tags. These values come directly from the tag cloud view.
Next are the various tag fields themselves. Now...before you start going off...I know that this is cumbersome to build the first time. However, I decided to strike a balance between functionality, ease to maintain and ease for the developer to understand, so it is what it is! :-) If you decide to use this technique, it would be a good idea to try to gauge how many tags you have before you build it. My personal preference is to limit a tag cloud to no more than 40 or 50 tags (I like less). Beyond that number is just too much visual noise for my taste. However, this could expand to as many fields as you want to create.
The field values themselves are populated in the PostOpen event. This event holds the meat of the code, as it implements the tag cloud algorithm to allow us to determine how large (from a font size perspective) each tag should be. There are variety of these algorithms available on the web, and I won't belabor them here. For our purposes, just know that I selected a common one and implemented it in formula language. The code loops through each value of the num_CategoryTotals field, determines how many entries there are for that tag and then uses that number in the algorithm to set the font size, plugging the value of the current tag into the txt_Tag# field that corresponds to the counter in the loop.
If you'd like to use a different tag cloud algorithm, just substitute your code as necessary.
The final part of the equation is to add a hotspot around each tag field. This hotspot will filter the view that you are displaying to the end user so that it only shows the given tag (category). In order to do this, we make use of the @SetViewInfo command. If you are not familiar with this command, it was added in R6 and allows you to display only documents from a given category in a categorized view. Armed with this tool, we open the view in question, make sure all the categories are expanded (or else you can end up with what appears to be a blank view) and then perform @SetViewInfo, using the given tag as the filter string.
One other note: You may want your tag cloud to have different colors. Not only does this provide visual interest, but it also can provide another clue as to the relative weight of a given tag (i.e. tags with the same color have close to the same number of entries). You add color in one of two ways. You can set the color values using formula language in the PostOpen event, or you can just apply color to the individual tag fields. The advantage of the first option is that it does respect the concept of relative weight of tags, but the disadvantage is that you are limited to the 15 colors allowed in @Command([TextSetFontColor]). With the second option, you can use any color you want, allowing you to make the tag cloud fit better with the design of your application. What you lose here, however, is the idea of relative weight since you are randomly choosing the colors. As always, it's a judgment call. Use whatever concept works best for you.
Once you put all of this together, all that is needed is to drop your tag cloud form into a place that makes sense. In most cases, a tag cloud will be most compelling when included alongside a view, so if you are building a frameset with navigation elements in one frame and a Notes view in another, the tag cloud should be included in one of the navigation frames.
When complete, the generic, non-styled version looks something like this:
But a little more work integrating it into the design of your application can give you something like this:
Now that is all said and done and I know what you are thinking: "Give me the code and sample database already!". OK, OK. Here we go:
I've included two downloads below. One is the complete design pattern database that was used at Lotusphere. This has all of the code and you can see how it was customized for the specific database in question. (This is a database that is about 10 years old...created in R4.6 or R5, I think, and I reskinned it for use as a demo). The other download is the very generic implementation of the tag cloud with just the tag cloud components in it. The idea is you should be able to grab these design elements, throw them into your database and be up and running with a tag cloud in a few minutes. I've included the instructions to add the tag cloud to your application in the Using This Database document. Download the database and dig in to give it a try.
I know there are a lot of improvements that can be made here, but my hope is that this gets the ideas going. I haven't seen an implementation of a tag cloud in the Notes client from the blogsphere yet, but I can't wait to see what you all come up with based on this skeleton. Please let me know and if you'd like, I can share your results here.
*Download the complete Lotusphere Demo
*Download the tag cloud design elements database