jQuery Tag Cloud [en]
Here is how I done the tag cloud of my blog. It is done mostly in jQuery. All my site is static and pages are generated with nanoc. It is (in my humble opinion) the modern geek way to make a website.
This is why I’ll give only a Ruby Generator, not a full javascript generator. But you can easily translate from Ruby to Javascript.
Here is what you should obtain:
jQuery
Here is the simple jQuery code:
$(document).ready( function(){$('.list').hide();} );
function tagSelected(id) {
$('.list').hide();
$('#'+id).fadeIn();
$('.tag.selected').removeClass('selected');
$('#tag_'+id).addClass('selected');
}
This code will hide all the div containing links to articles containing the tag. And create a function do show the div containing the tag.
For each tag I create a span element:
<span style="font-size: 1.0em;"
class="tag"
onClick="tagSelected('[TAG]')"
id="tag_[TAG]">
[TAG]
</span>
and a div containing links associtated to this tag:
<div id="[TAG]">
<h4>[TAG]</h4>
<ul>
<li> LINK 1 </li>
<li> LINK 2 </li>
</ul>
</div>
nanoc
Here is how I generate this using nanoc 2.
If you want to make it fully jQuery one, it shouldn’t be too difficult, to use my ruby code and translate it into javascript.
In a first time tags correpond of the list of all tags.
def tags return @page.tags.join(', ') end
A function to create a data structure associating to each tag its occurence.
# generate an hash tag => number of occurence of tag def tagNumber tags={} @pages.each do |p| if p.tags.nil? next end p.tags.each do |t| if tags[t] tags[t]+=1 else tags[t]=1 end end end return tags end
I also need a data structure who associate to each tag a list of pages (at least url and title).
# generate an hash tag => [ page1, page2 ... ] def tagRefs tagLinks={} @pages.each do |p| if p.tags.nil? next end p.tags.each do |t| if tagLinks[t].nil? tagLinks[t]=[ p ] else tagLinks[t] <<= p end end end return tagLinks end
Calculate the real size of each tag to be displayed.
I choosen not to use the full range of size for all the tag. Because if no
tag has more than n (here 10) occurences, then it doesn’t deserve to be
of the maximal size.
def tagRealSize tags=tagNumber max=tags.values.max min=tags.values.min # size in CSS em. minSize=1.0 maxSize=2.5 tagSize={} tags.each do |t,n| if ( max == min ) tagSize[t]=minSize else # normalized value between 0 and 1 # if not tag appear more than 10 times, # then it cannot have the maximal size tagSize[t]=[ ( n - min + 0.0 ) / ( max - min ) , (n - min) / 10.0 ].min # from normalized size to real size tagSize[t]=( tagSize[t] ) * (maxSize - minSize) + minSize end end return tagSize end
Finaly a function to generate the XHTML/jQuery code
# generate an XHTML/jQuery code for tag cloud def tagCloud tagLinks=tagRefs tagSize=tagRealSize # begin to write the code tagCloud=%{<script type="text/javascript"> $(document).ready( function(){$('.list').hide();} ); function tagSelected(id) { $('.list').hide(); $('#'+id).fadeIn(); $('.tag.selected').removeClass('selected'); $('#tag_'+id).addClass('selected'); } </script><div id="tagcloud">} # Creation of the tags <span> tagSize.sort{|a,b| a[0].downcase <=> b[0].downcase}.each do |t,s| tag_in_id=t.gsub(/\W/,'_') # HTML protected version of the tag # for example, replace ' ' by ' ' protected=t.gsub(/&/,'&').gsub(/ /,' ').gsub(/</,'<').gsub(/>/,'>') tagCloud <<= %{ <span style="font-size: #{s}em;" class="tag" onClick="tagSelected('#{tag_in_id}')" id="tag_#{tag_in_id}"> #{protected} </span> } end tagCloud <<= %{</div><div id="hiddenDivs" >} # Creation of the divs containing links associated to a tag. tagLinks.each do |t,l| tag_in_id=t.gsub(/\W/,'_') tagCloud <<= %{ <div id="#{tag_in_id}" class="list"> <h4>#{t}</h4><ul>} # generate the link list l.each do |p| tagCloud <<= %{<li><a href="#{p.path}">#{p.title}</a></li>} end tagCloud <<= %{</ul></div>} end tagCloud <<= %{</div>} return tagCloud # yeah I know it is not necessary end
You can download the complete file to put in your ‘lib’ directory. Beware, it is a nanoc 2 version, you’ll have to make some small changes like replace @pages by @items to be nanoc3 compatible.
Of course to be nice you need the associated CSS
// Change the color when mouse over .tag:hover { color: #cc0000; } // Change the color when tag selected .tag.selected { color: #6c0000; } // a bit of space and pointer cursor .tag { cursor: pointer; margin-left: .5em; margin-right: .5em; }
That’s all folks.