Building a jQuery-Powered Tag-Cloud
A tag-cloud is a great way of showing visitors to your blog the main topics of interest that are available. There is also additional information contained in a tag-cloud. Aside from the actual links themselves, which give people an idea of the subjects that your site covers, they can also show how popular the different subjects are. Another great thing about tag-clouds is that they can be used to describe the frequency of anything; you can link to articles, blog posts, images, video, or anything else that you have in abundance on your site.
Tag-clouds are easy to do badly; whether from a design perspective or from a code perspective. Thanks to jQuery, it’s also easy to do well. We’ll be using the hot new 1.3 version of jQuery for this example and will be working with PHP and MySql to provide a JSON feed of our tags. Getting the tags into a database in the first place is beyond the scope of this tutorial, but it’s a simple enough matter to retrieve and pass them to a waiting page via AJAX.
Getting Started
Let’s make a start on the page that the tag-cloud will be shown on; in a new file in your text editor create the following page:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<link rel="stylesheet" type="text/css" href="tagcloud.css">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>jQuery Tag Cloud</title>
</head>
<body>
<div id="tagCloud">
<h2>Tag Cloud</h2>
</div>
<script type="text/javascript" src="jquery-1.3.min.js"></script>
<script type="text/javascript">
$(function() {
//get tag feed
$.getJSON("http://localhost/jquery/tagcloud.php?callback=?", function(data) {
//process JSON object
});
});
</script>
</body>
</html>
Save this as tagcloud.html. At this stage we have almost nothing on the page, just a simple container for the tag-cloud and a 2nd-level heading within the container. Any other elements we need can be created as and when they’re required. We link to a stylesheet in the head for some styling which we’ll add later on, and at the end of the body we link to jQuery. We make the request for the JSON response in a custom script block after the reference to jQuery.
getJSON
We use the $ alias to call the getJSON jQuery method, which is a higher-level abstraction of the ajax method; normally jQuery methods are called on objects that are references to elements, but because we’re not referencing any elements yet we can use the jQuery alias instead. This also means that the jQuery object will not be returned by the method. Instead the xmlHTTPRequest is passed back.
The getJSON method accepts two arguments in this example (although more can be used if necessary); the first is the URL to which we are making the request. As we’ll be receiving a JSON object, it makes sense to use getJSON. We could use the ajax method, but would then need to configure more properties of the request (such as the dataType), so using this saves us a bit of time and coding. At the end of the URL we specify a JSONP callback – ?callback=? – which will enable the browser to directly manipulate the JSON object, even if it comes from another domain, without any additional server-side processing.
The Callback Function
The second argument is the callback function that we want to execute once the object is returned to the page. We haven’t put any code in this function yet, because we don’t have the JSON object to work with. We can come back to this page in a little while once we’ve written the PHP. I said a moment ago that no server-side processing is needed when working with JSONP callbacks, and yet we’re now going to go off and write some PHP. This is only because no one is providing the data we want So we have to create it ourselves. If someone were providing a JSON feed of popular tags, we could still use the same jQuery code to request and process it.
Some PHP
You’ll need to have access to a web server in order to run the file that we’re about to create, but this could be your own local web server that you use for development, or it could be the server your site or blog is hosted on. In a new page in your text editor add the following code:
<?php
//connection information
$host = "localhost";
$user = "root";
$password = "your_password_here";
$database = "tagcloud";
//make connection
$server = mysql_connect($host, $user, $password);
$connection = mysql_select_db($database, $server);
//query the database
$query = mysql_query("SELECT * FROM tags");
//start json object
$json = "({ tags:[";
//loop through and return results
for ($x = 0; $x < mysql_num_rows($query); $x++) {
$row = mysql_fetch_assoc($query);
//continue json object
$json .= "{tag:'" . $row["tag"] . "',freq:'" . $row["frequency"] . "'}";
//add comma if not last row, closing brackets if is
if ($x < mysql_num_rows($query) -1)
$json .= ",";
else
$json .= "]})";
}
//return JSON with GET for JSONP callback
$response = $_GET["callback"] . $json;
echo $response;
//close connection
mysql_close($server);
?>
Save this as tagcloud.php. For this example, I’m assuming you have MySql installed and configured, and have setup a database called tagcloud. Within this database I’m also assuming there is a table called tags. This table will have rows of the tags and the frequency of the occurrences of these tags. I want to stress that this isn’t production-level code because security has not been a factor in its design; we need somewhere to get our AJAX response from in this example and this code will give us that somewhere.
Let’s briefly look at what we’ve done.
//connection information $host = "localhost"; $user = "root"; $password = "your_password_here"; $database = "tagcloud";
First we setup the connection information that we’ll need in order to connect to the database. Make sure you replace your_password_here with the actual password you set to access MySql. We then connect to the database and set the query that we’ll use to access the data from the tags table.
//start json object
$json = "({ tags:[";
//loop through and return results
for ($x = 0; $x < mysql_num_rows($query); $x++) {
$row = mysql_fetch_assoc($query);
//continue json object
$json .= "{tag:'" . $row["tag"] . "',freq:'" . $row["frequency"] . "'}";
Next we create the string that will start the JSON object, before looping through each row in the table and performing the query. We continue to build the JSON string within the for loop, adding the data from both fields of the current row as properties and values.
//add comma if not last row, closing brackets if is
if ($x < mysql_num_rows($query) -1)
$json .= ",";
else
$json .= "]})";
}
We perform a simple check on each iteration of the loop using the for conditional to see whether we’re reading the last row in the table; if we aren’t we use a comma to separate each object, if we are we close the object. The format of the JSON object will be individual record objects within a single container array, within an outer object.
//return JSON with GET for JSONP callback $response = $_GET["callback"] . $json; echo $response; //close connection mysql_close($server);
We then echo the response back to the client using a GET request; this is needed in order to make use of the jsonp callback in our main page. We need to specify the name of the URL parameter that follows the URL of the in the JavaScript, which in this example is simply callback. We can’t tell it the name of the function that we want to pass it to however, because the function is anonymous. jQuery will handle this for us and ensure the data is passed to the correct function.
Once we’re done, we close the connection. At this stage, we still can’t see anything on the page, but if you run the run from a content-serving directory of your web-server and use the NET tab of Firebug, you can see that data that is being returned to the page:
Processing the json
Now that we have some JSON to work with, let’s go back to the HTML page and do something with it. Our fist task is to process it to extract the data; in tagcloud.html, remove the comment we left within the callback and add the following code:
//create list for tag links
$("<ul>").attr("id", "tagList").appendTo("#tagCloud");
//create tags
$.each(data.tags, function(i, val) {
//create item
var li = $("<li>");
//create link
$("<a>").text(val.tag).attr({title:"See all pages tagged with " + val.tag, href:"http://localhost/tags/" + val.tag + ".html"}).appendTo(li);
//add to list
li.appendTo("#tagList");
});
First we create a new list element, set its id attribute, and append it to our container on the page. As the data in the JSON object isn’t in any particular order, an unordered list meets our requirements. Then we use the each() jQuery method to iterate over all of the items in the array nested within our JSON object. For each iteration, we create a new list item and a new link.
We set the text of each link to the value of the tag property of the current object from our JSON object, as well as sett the title and an href. The href used will depend largely on how the pages showing the tags are going to be generated, we could generate a search results style page listing all of the pages that matched whichever tag was clicked using PHP or .NET easily enough (the results page is also beyond the scope of this tutorial). The link is then appended to the list item, and both are appended to the <ul>.
At this stage, our page should appear something like the following:
It’s certainly a list of links, but a tag cloud it isn’t. We can easily fine tune the appearance of the widget with a little CSS. Let’s do this next. In a new file in your text editor, add the following code:
#tagCloud {
width:290px; background-color:#575454; text-align:center; padding:5px;
overflow:auto; font-size:70%; font-family:arial;
}
#tagCloud h2 {
color:#ffffff; font-size:2.5em; margin:0 0 10px 0;
background:url(images/cloud.gif) no-repeat 0; padding:15px 0 15px 80px;
}
#tagList { margin:0; padding:0; }
#tagList li {
list-style-type:none; float:left; margin:0 10px; height:35px;
}
#tagList li a { text-decoration:none; color:#ffffff; }
#tagList li a:hover ( text-decoration:underline; }
Save this as tagcloud.css. The styles used are a mixture of functional and aesthetic rules, such as floating the list items, and setting their dimensions used to control how the widget functions. I’ve kept the styles as minimal as possible, as no doubt you’ll need to change most of the purely visual styles to fit in with the theme of your existing site.
One important point to note is the font-size we’ve used; a font-size of 70% is set on the outer container element; this represents the smallest text that will appear in the tag cloud. We’re going to be adjusting the font size of some tags using em units in the final part of the script. So setting a baseline font-size is important for consistency.
Now when you run the page, it should appear as follows:
Finishing the Script
One of the hallmark attributes of the tags in a tag cloud is that the individual tags are sized according to their frequency of occurrence; the more popular a tag is, the bigger it’s displayed. We can easily make use of the freq property within our JSON object to resize each link according to its popularity. In between creating the new link and appending it to the unordered list in our script, add the following code:
//set tag size
li.children().css("fontSize", (val.freq / 10 < 1) ? val.freq / 10 + 1 + "em": (val.freq / 10 > 2) ? "2em" : val.freq / 10 + "em");
In truth, the css method could easily be chained to the jQuery object directly after we set the link’s title attribute, but they’re separated here for better readability. Within the css method, we specify the fontSize style attribute and use the standard JavaScript ternary conditional to check whether the current value of the freq property divided by 10 is less than 1. If it is, we add 1 to the figure and then concatenate the string em on the end. This will ensure that none of the tags have a font-size of less than 1em, which is equal to our 70% style rule set on the container element.
However if the value of the freq property divided by 10 is not less than 1, we then check (using another ternary, the equivalent of nesting for loops) whether it is greater than 2; if it is, we simply use 2em as the value of the font-size property. Any elements with a font-size of 2em will be twice the size of our original 70% baseline, which is probably as big as any tag in this type of widget should get. Any values greater than 1 but less than 2 are used in their fractional form to set a font-weight of between 1 and 2 ems. The final page should now appear something like the following screenshot when viewed in a browser:
Summary
In this tutorial we’ve seen how “easy” it is to build a basic tag cloud which retrieves the tags to display as part of an AJAX request directly after page load. It is easy to resize each tag depending on its frequency using a sensible range of text sizes. Although the overall appearance of the widget has been left rather minimally styled, it should be easy to build on this foundation to create something that is beautiful as well as functional.


I think it’s really stupid to make an asynchronous request to get “static” (during visit time) data like the tagcloud. It can be done simply in PHP… AJAX is cool but when it’s needed!
nothing is stupid
we atleast learned to use ajax
great tutorial
@isra: the reason for the AJAX instead of additional server-side code is that thanks to JSONP we can process JSON objects from other domains without being subjected the the browser’s inherent xdomain restrictions. If a site was providing a JSON feed of popular tags, we could use the same jQuery code to request and process this object without needing any PHP or a database :)
Thanks man! Really enjoyed your tutorial, will be back for sure. I also applaud your patient and far-sighted approach to us, the audience, nicely moderated. All in all this has added diversity and perspective to a great tutorial.
1 + 1 > 2
Love it. I really appreciate your patient explanations of the code that are so often lacking in other tutorials. I hope you’ll keep posting tutorials. Thanks.
I love this one . It’s so simple to read and learn!!
Great tut
Great Tutorial,
Think out of some tag clouds ive seen before this looks one of the best. If I was to use one however I would probably go with the jquery tag cloud just because I’m more familiar with that.
@Dan – I like the idea of bringing in the tags from any JSON endpoint and the jQuery to inject it into the markup.
However, I think you made hard work of your local JSON generator process, connecting to MySQL, parsing the result, etc.
A much easier solution that still maintains the objective of this tutorial is to forget all the DB stuff and modify the PHP file to simply this:
$response = $_GET["callback"] .
'({ tags: [
{ tag: "Ajax", freq: "10" },
{ tag: "CSS", freq: "20" },
{ tag: "XHTML", freq: "30" },
{ tag: "jQuery", freq: "30" },
{ tag: "JavaScript", freq: "5" },
{ tag: "XML", freq: "10" }
]})';
echo $response;
Because this does not gracefully degrade for accessibility. I would generate the whole #tagCloud container so that someone without JavaScript would see nothing (They won’t feel cheated) and those with JS get a nice progressive enhancement.
Sweet! This is my favorite tutorial. I am about to post an update to my blog listing the Top 50 Web Technologies in Boston (see link below) and I want to use this tag cloud along with it. I plan to test over the weekend.
P.S. I want to be a “Sexy Web Design” -er.
The PHP for generating the JSON object has been pointed out to be a bit less than optimal. I’ve found using arrays to construct tags like this to be the easiest way to process the data and. I can then use join() to join the pieces, allowing it to put the commas where necessary:
//start json object
$json = array();
//loop through and return results
for ($x = 0; $x < mysql_num_rows($query); $x++) {
$row = mysql_fetch_assoc($query);
//continue json object
$json[] = “{tag: ‘${row['tag']}’,freq:’${row['frequency']}’}”;
}
//return JSON with GET for JSONP callback
echo $_GET["callback"] . ‘({ tags:[' . join(',', $json) . ']})’;
Hi Dan,
Thanks for a great tutorial and thanks for not cutting corners by using PHP functions to encode the json string. It’s nice to know what the string will look like without having to view it in a 3rd party app like firefox plugins. There are many different ways to do this, like you first explained. I personally will be using this as part of a module in a cms, and putting tags in a PHP file is out of the question for users that would use my module. Your simple example will give me the basics so that I can expand the concept and add more functionality.
I have been getting familiar with jQuery recently and the more I get into it, the more I’m impressed with it. When I first heard about jQuery I was definitely intimidated by it since I had no previous background with javascript, but I soon realized once you get the basics down its not very hard to pull of some neat effects.
Awesome! very useful. Thank you
WOW excelent cloud, but, how is the aplicattion in asp.net????
this gives me a lot of idea on how to create my own tag cloud. very nice tutz! thanks for this :)
very good.
what’s add-on with “jsss” icon in the status bar of your firefox?
Thanks so much! I wrote a Python server-side app that works with your example, now in Pastebin. http://pastebin.ws/96h31d
Cool :P
Hi, sorry I have 2 total n00b questions.
In this tutorial do you have the files located in a folder titled “jquery” thats on the root level thus: “localhost/jquery/tagcloud.php”? if not what’s the file layout? Where do the jquery and json files go? In the jquery folder? localhost?
Also in the tagcloud database, the table is called “tags” and the columns “tag” and “frequency” right?
How would you integrate this in a sidebar thats made out of a list?
like this:
…
…
I tried this and several variations but the document doesn’t pick up the script.
Any suggestions?
Thank to this tut. I’ll be back on this really useful site.
Article vraiment très bon.
Merci
Thanks for sharing this code, very interesting article. I have found a completely free (including commercial websites) tag cloud script written in PHP on http://www.softwaremastercenter.com/free-tag-cloud-generator-script.html. I like it because it has a built-in text-to-tags parser and it filters out common words – if you inspect the code you will see maybe a thousand common words that will be removed. For fact, I have actually added more words to it. The styling options are pretty good for free software plus there is an option to get only the array of tags with weights and do your own styling. I started thinking about how to combine your code and their code.
This is a great article! It helped me write some code to integrate it into our ecommerce sites and works a treat. I’ve used it a few times now with great success and the stats show the clouds really do help…
Many Thanks
Thanks a lot..
I’m a newbie in php I have uploaded files in my host but i don’t know how to create a table and wich value insert in it
Can you insert in source code a file or a query to create table automatically?
thanks
Thanks for sharing this code, very interesting article. I have found a completely free (including commercial websites) tag cloud script written in PHP on http://www.softwaremastercenter.com/free-tag-cloud-generator-script.html. I like it because it has a built-in text-to-tags parser and it filters out common words – if you inspect the code you will see maybe a thousand common words that will be removed. For fact, I have actually added more words to it. The styling options are pretty good for free software plus there is an option to get only the array of tags with weights and do your own styling. I started thinking about how to combine your code and their code.
Why would you need to write all these extra lines of code to display a tag cloud? If you’re making a tag cloud, it’s *probably* going to be on your own website, where you *already* have an open connection to the database and access to your article tags. I think you just took what is “hot” right now (jQuery, JSON) and wrote a tutorial for it. Just do it the normal way: at runtime with PHP. I mean, hell. Why the extra browser calls? Why the extra MySQL connection? Why the JSON? It just seems pointless to me.
And if you’re going to say something like, “it’s asynchronous!” Come on… My blog loads in like half a second. I don’t think anyone is going to care.
On a side note, I’m probably just ranting because new technologies come out every week and everyone and their mother thinks that the new technology is “the way it should be done” when last weeks technology does it just fine.
Like Ruby on Rails. HA. What a joke.
Perfect, thanks
worked this is really a very nice tag cloud..
Very nice tutorials!
Great tutorial, thanx a lot :)
I think this is working fine in all browsers (firefox ,chrome and safari ) but not in IE8 ?? any reason ??
The JSON respone is not being appended to empty tag !
This is the most stupid tag clouds jQuery plugin i have ever seen!!! Why the hell do i need to make an ajax call to get a stream of data after getting page elements while i can retrieve the tag clouds with the same page load!! this is just as stupid as a monkey’s crap pulling over from a stupid elephant ass!
Great tut, helped me loads!!
Nice and simple tutorial. Here I am facing one problem that it is working in Firefox and other browser but not in IE.
I want something, such as a jquery script, that executes a python script
that does nothing more than immediately display a line of HTML chosen
based on the url of the calling HTML page, immediately upon page open or
refresh, a different line for each URL. Initially, it can show just the
URL, but the eventual solution is to use the URL as a dictionary key to
select the line as a value of that dictionary.
mod_python is not an option as we do not have access to Apache, nor
is xBitHack to enable server-side includes. Available tools are
javascript and python.
Some background. This is simple javascript to display the calling url:
var myurl = document.location.href;
document.write(“” + myurl + “”);
And I know how to create a link that opens a page to execute the .py script when one clicks on it:
Here
Here is the python script so far:
#!/usr/bin/env python# This outputs a copyright notice to a web page
import cgiprint “Content-Type: text/html\n”
form = cgi.FieldStorage()
thisurl = form.getvalue(“myurl”)
print “”"
“”"
print “”"
Copyright © 1995-2011 Constitution Society. Permission granted to copy with attribution for non-profit purposes.
“”"
print “”"
“”"
print thisurl
But one has to click on “Here”. I want to have the copyright notice to appear immediately.
The problem is that each page needs its own copyright notice, which
is subject to change as years are added to the range of each.
One approach to getting the referring URL can be done with
import os
print os.environ['HTTP_REFERER']
great stuff … as a python lover the script-idee from @John gives my the kick!
Chequen esta solución de administración multiplataforma completa para el centro de datos virtualizado http://bit.ly/nBWU3P
Is this possible to make a tag cloud using jQuery only…??
Use this: http://cssglobe.com/post/4581/tag-clouds-styling-and-adding-sort-options – it took me 10 minutes to set up instead of an entire morning trying to sort out the bugs in this. Even when I finally got it “working” the tag sizes didn’t work properly.
Thanks for tutorial. Keep productives …
Nice article