Overview :
Nowadays we found all the websites have special type of panel, whether left or right side of the page, with different styled words or phrases. Some of them are more or less styled, like bold and size of the font. These are the nothing but CloudTags, which leads us to the different pages related to that perticular word or phrase.
There are lots of techniques to do such a like stuff. I have searched for all those for Static Webpages and found few links like below.
http://24ways.org/2006/marking-up-a-tag-cloud
http://webdesign.about.com/od/csstutorials/a/aa011407.htm
Etc...
But, all those are not enough for me to do, what I wanted because all of them used to statically apply the CSS. So, when we require making the word or phrase bolder then there would require to change the CSS on each page and it is not the proper way to deal with.
Solution :
So, I have tried to resolve the problem by using following technologies.
1. XML/XSLT
2. JavaScript/CSS
1. XML/XSLT
I have created two simple Xml file which contains the projects information, let’s say Projects.xml
Projects.xml
<?xml version="1.0" encoding="utf-8" ?>
<Projects>
<Project type="Migration">
<Item>1</Item>
<Item>2</Item>
</Project>
<Project type="File Upload">
<Item>1</Item>
<Item>2</Item>
<Item>3</Item>
<Item>4</Item>
<Item>5</Item>
</Project>
<Project type="SharePoint">
<Item>1</Item>
<Item>2</Item>
<Item>3</Item>
<Item>4</Item>
</Project>
<Project type="Silverlight">
<Item>1</Item>
</Project>
<Project type="Cold Fusion">
<Item>1</Item>
</Project>
</Projects>
This xml file contains Project nodes, which actually specifies the type of project. Here I have added random types of the projects.
And each Project node contains the Item, which are the actual name of the projects done, here I have used only numbers, because it just to show you the working and there is nothing concern about the data, I have used here.
But the actual require format of the xml file is something different as below,
NewProjects.xml
<?xml version="1.0" encoding="utf-8"?>
<Projects>
<Project type="Cold Fusion" Num="1" url="projects.html?projecttype=Cold Fusion">
</Project>
<Project type="File Upload" Num="5" url=" projects.html?projecttype=File Upload">
</Project>
<Project type="Migration" Num="2" url=" projects.html?projecttype=Migration">
</Project>
<Project type="SharePoint" Num="4" url=" projects.html?projecttype=SharePoint">
</Project>
<Project type="Silverlight" Num="1" url=" projects.html?projecttype=Silverlight">
</Project>
</Projects>
In this xml file, we can see that it is simple to understand by developer but it is not easy to maintain by the data entry operator. The person, who is entering the data, can make mistakes or may enter wrong data and ultimately there would be generated wrong CloudTags .
This xml file is same as Projects.xml file with additional attributes in the Projects node.
Num: This is the number which shows the number of projects done in that particular type(Category).
url: This is the url to redirect to the page which contains the information regarding that particular project type. Here we have taken only a single url and passing project type as a bookmark in the querystring.
To make process simpler for data entry I have used xslt to apply style to the Projects.xml and generates the NewProjects.xml.
Projects.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="Projects">
<xsl:for-each select="Projects/Project">
<xsl:sort select="@type"/>
<xsl:element name="Project">
<xsl:attribute name="type">
<xsl:value-of select="@type"/>
</xsl:attribute>
<xsl:attribute name="Num">
<xsl:value-of select="count(Item)"/>
</xsl:attribute>
<xsl:attribute name="url">
<xsl:text> projects.html?projecttype=</xsl:text>
<xsl:value-of select="@type" disable-output-escaping="yes"/>
</xsl:attribute>
<!--<xsl:copy-of select="Item"/>-->
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
By using the xslt, we even can generate HTML but that would be seen later on.
In this xslt file I have there is comment
<!--<xsl:copy-of select="Item"/>-->
This is actually to renders the Item nodes under Project nodes, like Projects.xml, which are not required here for me.
2. JavaScript/CSS
Here is the javascript which actually gets the xml/xslt files and generated the output using DOM.
tagCloud.js
var divTagId;
var xml;
var xsl;
var xmlOutput;
function loadXMLDoc(fname) {
var xmlDoc;
// code for IE
if (window.ActiveXObject) {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.load(fname);
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument) {
try {
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.async = false;
xmlDoc.load(fname);
}
catch (e) {
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET", fname, false);
xmlhttp.send(null);
xmlDoc = xmlhttp.responseXML.documentElement;
}
}
else {
alert('Your browser cannot handle this script');
}
return (xmlDoc);
}
function insertTable() {
tbl = document.createElement('table');
tbl.style.width = "100%";
tbl.style.height = "100%";
tbl.style.background = 'transparent';
var row = tbl.insertRow(0);
var cl = row.insertCell(0);
cl.style.padding = "10px";
cl.style.align = "justify";
oTableContainer = document.getElementById(divTagId);
oTableContainer.appendChild(tbl);
var doc = xmlOutput.documentElement; //.selectNodes('Project');
if (doc.hasChildNodes()) {
var itemElements = doc.getElementsByTagName("Project")
var max = parseInt(itemElements.item(0).getAttribute("Num"));
var min = parseInt(itemElements.item(0).getAttribute("Num"));
for (var i = 1; i < itemElements.length; i++) {
{
var tmp = parseInt(itemElements.item(i).getAttribute("Num"));
if (max < tmp)
max = tmp;
if (min > tmp)
min = tmp;
}
}
var minFontSize = 11;
var maxFontSize = 32;
var diff = max - min;
var offset = parseInt((maxFontSize - minFontSize) / diff);
var htmlString = '';
for (var i = 0; i < itemElements.length; i++) {
{
var tmp = parseInt(itemElements.item(i).getAttribute("Num"));
var fontSize = minFontSize + ((tmp - min) * offset);
htmlString += ' <a href="' + itemElements.item(i).getAttribute("url") + '" style="font-size: ' + fontSize + 'px;line-height: ' + (minFontSize + (diff * offset)) + 'px;color: #1E3695;">' + itemElements.item(i).getAttribute("type") + '</a> ';
} }
cl.innerHTML = htmlString;
}
}
function displayResult(divTagIdArg, xmlArg, xslArg) {
divTagId = divTagIdArg;
xml = loadXMLDoc(xmlArg);
xsl = loadXMLDoc(xslArg);
// code for IE
if (window.ActiveXObject) {
xmlOutput = new ActiveXObject("Microsoft.XMLDOM");
xmlOutput.async = "false";
xmlOutput.loadXML(xml.transformNode(xsl));
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument) {
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToDocument(xml, document);
var xmlSerializer = new XMLSerializer();
parser = new DOMParser();
xmlOutput = parser.parseFromString(xmlSerializer.serializeToString(resultDocument), "text/xml");
}
insertTable();
}
And we only require to call the displayResult() javascript function by passing id of the division tag, relative path of the xml file, and relative path of the xslt file.
Limitations : It is intendended to use and tested in IE7.0, firefox3.0.11, and Opera 9.27 only.
Example :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Cloud Tags in static pages...</title>
<script src="Javascripts/tagCloud.js" type="text/javascript"></script>
</head>
<body onload="displayResult('divCloudTag','XmlDataSource/Projects.xml','XmlDataSource/Projects.xslt');">
<div id="divCloudTag" style="width: 400px;height:200px;vertical-align:top;direction:ltr;display:inline;">
</div>
</body>
</html>
Output:

Note : Javascrip/CSS guys can make it to work with other browsers and also can simplyfiy the secario.
Thanks,
Ramesh N Vagh,
Software Engineer,
Prakash Software Solutions Pvt. Ltd.
Vadodara