How to make a tag cloud
Posted on 22 Jan 2008 9:39pm by Aleks Bochniak
Tag clouds or 'tagging' has been around used the web for a couple of years now, it's not relatively new or unique. However, using tags and/or tag clouds on your web-site can add value to your content and be beneficial to your users.
What is a tag cloud exactly? Wikipedia has a good definition. A simple example is just to your right in the side column under the heading 'Tags used'.
Creating one of these can be a little tricky in MySource Matrix, especially the GPL version (no lovely search module here). Since we can't use php code in our pages, we have to use javascript to do the hard work for us.
Some clarification
There are 3 different ways to tag a page or asset with terms. One way is to create a lexicon of terms in a thesaurus and use the tagging screen to select these terms, however it's not possible to print out which terms are used on the front-end and their associated weighting. Kind of disappointing really.
The other two ways involve metadata. One using a thesaurus as a metadata field type, or using a multiple text field type. I prefer the multiple text option, as it allows me to enter free text as terms and removes the hassle of maintaining a definitive list separate to my content.
Building the cloud
First thing we need to do is to create a metadata schema with a default section and one metadata field called 'tags' of type "multiple text field".
Secondly create a few pages in a folder, apply our metadata schema and tag some terms. I have a few dummy pages which I have tagged with some latin text.
Below is part of a screenshot of one page's metadata screen.
Next we need to create an asset listing page called 'tag cloud' to find all the pages in the folder. Nothing tricky needs to be defined for the asset listing, just the types of assets to list "Standard Page" and root node; being your folder.
I would suggest for all the divs created and used in this example be of type "Raw HTML" and style "Raw HTML". On the Type Formats -> Default Format page contents enter the following without trailing spaces:
%asset_metadata_tags%;
This tag should spit out something like (with the semicolon at the end):
lorem; lipsum; consectetuer; platea; nunc; morbi; mauris; venenatis; donec; primis; nulla; leo id; morbi; arcu; nunc; aliquam; mollis; elementum; commodo; nulla; tristique; pretium; ultrices; lorem; nunc; ultrices; leo; accumsan; nulla; condimentum; cursus; quam; posuere; curae; ipsum; primis; lorem; leo id; nulla; ultricies; libero; loboritis; non; ante; morbi; tristique; senectus; pellentesque; aliquet; curae; nonummy; nulla; suscipit; magna; lorem; purus; sapien; cras; ligula; iaculis; suscipit; commodo;
Now we need some javascript to split that long string into an array of unique terms, ordered alphabetically and their frequency counted.
Javascript comes to the rescue
In my Design I am importing a javascript file which contains 3 functions that help sort the array of terms and assign a css class to the tag link.
function unique(x) {
tmp = new Array(0);
for(i=0;i<x.length;i++) {
if(!contains(tmp, x[i])) {
tmp.length+=1;
tmp[tmp.length-1]=x[i];
}
}
return tmp;
}
function contains(x, e) {
for(j=0;j<x.length;j++) {
if(x[j]==e) {
return true;
}
}
return false;
}
function getTagClass(z) {
var tagClass = "smallestTag";
if(z==smallest) {
tagClass="smallestTag";
} else if(z==largest) {
tagClass="largestTag";
} else if(z >= large) {
tagClass="largeTag";
} else if(z <= large && z >= medium) {
tagClass="mediumTag";
} else if(z <= medium && z >= smallest) {
tagClass="smallTag";
}
return tagClass;
}
In the Page Contents of the 'tag cloud' asset listing page, we need to pull in the list of tags with the %asset_listing% keyword and assign it a javascript string for processing. This string then needs to be split into an array, duplicates removed and sorted alphabetically.
<script type="text/javascript">
<!--
var a = '%asset_listing%';
var split = new Array();
split = a.split('; '); //string to array
var unique = unique(split);
unique.sort(); //sort alphabetically
We also need to find the number of times (frequency) a tag term is being used so we can assign a font size (with a css class) to it.
var frequency = new Array();
var counts = new Array();
var largest = 0;
var smallest = 1;
/* create array of tag counts and find sizes */
for(var i=0; i<unique.length-1; i++) {
var mullet=0;
unique[i] = unique[i].replace(/^\s+|\s+$/g, '') ;
for(var j=0; j<split.length; j++) {
if (unique[i]==split[j]) {
mullet=mullet+1;
}
frequency[i] = mullet;
}
}
Now, we need to do some simple maths to find the largest times a term has been used, the medium value, distribution and difference. The size of the tags will be from the smallest (1) to the largest (we still need to find it!).
for(var d=0;d<frequency.length;d++){
largest=Math.max(largest,frequency[d]); //find largest
}
var diff = largest-smallest; //difference, smallest is always 1
var dist = diff/3; //distribution
var large = 1 + (dist*2);
var medium = 1 + dist;
The following code is used to write out a paragraph with the tags linked to Google blogsearch, and style the link with their relevant size.
/* continue */
if(unique.length != 0) {
document.write('<p id=\"tags\">');
for(var i=0; i<unique.length-1; i++) {
var z=0;
for(var j=0; j<split.length; j++) {
if (unique[i]==split[j]) {
z=z+1;
}
counts[i] = z;
}
var size = getTagClass(z);
document.write('<a class=\"'+size+'" href=\"http://blogsearch.google
.com/blogsearch?q='+unique[i]+'\">'+unique[i]+'</a> ');
}
document.write('</p>');
}
//-->
</script>
So, that's basically it. There are probably a few ways to optimise the code and behaviour, but that's an exercise to come later when I have time. As a quick start it works very well.
Above is a image of a tag cloud I created using this code.







Comments
There are 4 comment(s) so far... say something?
24 Jan 2008 6:49am
Good write up.
04 Feb 2008 11:05pm
Great post, very helpful and will be implemented on a few sites here I've got on the run.
Thanks!
19 Sep 2008 2:28am
It seems your code always removes the last item passed to it. This also means the first item alphabetically is displayed last. Have you a fix for this?
20 Sep 2008 12:08pm
Do you have a page that puts all the code together? So the novice can learn? there seems to be some key gluecode missing