Tag cloud sorting
chombee <[email protected]> Thu, 01 Nov 2007 17:24:21 +0000
| Newsgroups | gmane.comp.web.pyblosxom.user |
|---|---|
| Message-ID | <1193937861.5639.37.camel@s0094060-desktop> |
Attached is a modified version of the tagcloud plugin. I couldn't get folksonomy to work so I'm using tags and tagcloud instead. Anyway, the tagcloud plugin outputs tags in a random order, which is not very useful. My version adds two new template variables: $alphabetical_tagcloud -- output tags sorted alphabetically $popularity_tagcloud -- output tags sorted by popularity. It also moves the "untagged" tag onto a line of its own at the bottom of the tag cloud. I don't think it makes sense to have "untagged" mixed in with all the other tags. This image shows the same tagcloud unsorted, sorted alphabetically, and sorted by popularity: http://www.23hq.com/seanh/photo/2562773/original Personally I think that by popularity looks cleanest, although alphabetical may be more useful if you're scanning for a particular tag. They have their pros and cons. The implementation is a bit ugly right now in two ways: Sorting tags by popularity added some code duplication. The whole file could do with some refactoring to handle this sort of option well. (You could add more options, to output tags as a list instead of a cloud, for example). It creates all four kinds of tag cloud every time the plugin runs, and stores each one in a different template variable. I don't really know how pyblosxom plugins work, I'm just hacking the existing ones that I use. Is there some way for a template to pass a parameter to the plugin telling it what kind of tag cloud to create? I recall seeing the syntax for something like this being discussed but I don't remember if it was an existing feature or a proposed one. Thanks ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ pyblosxom-users mailing list pyblosxom-users-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/pyblosxom-users
tag_cloud.py
(text/x-python, 7.8 KB)
"""
tag_cloud.py
* * *
chombee 2007-11-01 13:26:59
Added ability to sort tag clouds either alphabetically or by popularity. Adds two new template variables for sorted tag clouds. It's a bit ugly right now:
* Sorting tags by popularity added some code duplication. The whole file could do with some refactoring to handle this option well.
* It creates all four kinds of tag cloud every time the plugin runs. Is there some way for a template to pass a parameter to the plugin telling what kind of tag cloud to create?
Also moved the "untagged" tag to a line on its own at the bottom of the tag cloud.
* * *
Creates a tagcloud to compliment the tags plugin. Simply copy to your plugins directory and
enable in py['load_plugins'] if necessary. The tags plugin must be installed and properly
configured.
Simply add a #tags tag1[,tag2[...]] to your entry metadata section.
You should then define the following classes:
.smallestTag
.smallTag
.mediumTag
.bigTag
.biggestTag
.hugeTag
.hugestTag
.mostHugeTag
as well as
#tagcloud
The <size>Tag classes will be used on <a /> elements to represent the number of entries with
that tag.
in your CSS to fit your needs.
As of 1.3.1, tag_cloud supports the following config property:
py[ 'ignore_tags' ] = [ ] - Use to omit tags from the tagcloud.
py[ 'tag_url_display' ] = [ ] - Useful if you use mod_rewrite to redirect your tags url. Defaults to config['tag_url']
where 'ignore_tags' is a list of tags to ignore while generating the tag cloud. This way, if you have a
very widely used tag, such as "general", which is overwhelming your tag and isn't necessary, you can choose
to omit it.
As of 1.0.2, tag_cloud obeys the ignore_directories propery in pyblosxom.
Version 1.0.3 - Fixed an error choosing tag size; never used smallestTag
Version 1.1.0 - Fixed an error choosing tag size; was not properly choosing mincount. Also added
finer breakdown of distribution, better for smaller sites.
Version 1.2.0 - Added an "untagged" tag to the cloud after Joe accepted my untagged hack to his tags plugin.
Make sure you're using Tags v 2 2005/10/23 1:30:00 or later!!
NOTE: The "untagged" tag does not factor into the tag weightings, and will always be
shown using a .mediumTag class.
Version 1.3.0 - Added a "populartagcloud" variable, which takes the full "tagcloud",
removes anything which is not at least a "medium tag", and redistributes
the weightings. This is great if you have a lot of tags with only
one or two posts that don't pertain to the main content of your blog.
Version 1.3.1 - Added defaults for config[] parameters that weren't checked for
Fixed bug where mincount was always 1 instead of the actual mincount
"""
__author__ = 'Timothy C. Fanelli <[email protected]>'
__version__ = '1.3.1'
__url__ = 'http://www.timfanelli.com'
# Variables
import os, re, sys, string
def cb_prepare(args):
request = args['request']
config = request.getConfiguration()
data = request.getData()
maxcount = 1
tagcount = {}
ignoretags = []
if config.has_key('ignore_tags'):
config['ignore_tags']
ignoredirectories = config[ 'ignore_directories' ]
for root,dirs,files in os.walk( config['datadir'] ):
for file in files:
if not re.compile('.*\.txt$').search(file):
continue
entry_location = root + "/" + file
directory = os.path.dirname(entry_location)
if ( os.path.split( directory )[1] in ignoredirectories ):
continue
contents = open(entry_location,'r').read()
m = re.compile( '\n#tags\s*(.*)\n' ).search(contents)
if m:
tagstring = m.group(1)
tags = tagstring.split(',')
first = True
for tag in tags:
if ( tag in ignoretags ):
continue
count = 1
if tag in tagcount.keys():
count = tagcount[tag] + 1
tagcount[tag] = count
maxcount = max( count, maxcount )
else:
untaggedcount = 1
if "untagged" in tagcount.keys():
untaggedcount = tagcount["untagged"] + 1
tagcount["untagged"] = untaggedcount
mincount = maxcount
for tag in tagcount.keys():
mincount = min( mincount, tagcount[tag] )
data["tagcloud"] = createTagCloud( config, tagcount, mincount, maxcount )
data["populartagcloud"] = createPopularTagCloud( config, tagcount, mincount, maxcount )
data["alphabetical_tagcloud"] = createTagCloud( config, tagcount, mincount, maxcount, 'alphabetical' )
data["popularity_tagcloud"] = createTagCloud( config, tagcount, mincount, maxcount, 'popularity' )
def createPopularTagCloud( config, tagcount, mincount, maxcount, sort=None ):
distribution = ( maxcount - mincount ) / 6
popcount = {}
popmin = 999999
for tag in tagcount.keys():
count = tagcount[tag]
if ( count > ( mincount + distribution ) ):
popcount[tag] = count
popmin = min( popmin, count )
return createTagCloud( config, popcount, popmin, maxcount, sort )
def case_insensitive_cmp(a, b):
return cmp(a.upper(), b.upper())
def popularity_cmp(a, b):
return cmp(a[1],b[1])
def createTagCloud( config, tagcount, mincount, maxcount, sort=None ):
if tagcount:
tagurl = config['tag_url']
if config.has_key('tag_url_display'):
tagurl = config['tag_url_display']
tagcloud = []
tagcloud.append("<div id='tagcloud'>")
distribution = ( maxcount - mincount ) / 6
sortedtags = tagcount.keys()
if sort == 'alphabetical':
sortedtags.sort(case_insensitive_cmp)
elif sort == 'popularity':
items = tagcount.items()
items.sort(popularity_cmp,reverse=True)
sortedtags = []
for item in items:
sortedtags.append(item[0])
untagged = False # Does the 'untagged' tag exist?
for tag in sortedtags:
size = "mediumTag"
if tag == "untagged":
untagged = True
else:
if ( (int)(tagcount[tag]) == maxcount ):
size = "mostHugeTag"
elif ( (int)(tagcount[tag]) > ( mincount + ( distribution * 5 ) ) ):
size = "hugestTag"
elif ( (int)(tagcount[tag]) > ( mincount + ( distribution * 4 ) ) ):
size = "hugeTag"
elif ( (int)(tagcount[tag]) > ( mincount + ( distribution * 3 ) ) ):
size = "biggestTag"
elif ( (int)(tagcount[tag]) > ( mincount + ( distribution * 2 ) ) ):
size = "bigTag"
elif ( (int)(tagcount[tag]) > ( mincount + distribution ) ):
size = "mediumTag"
elif ( (int)(tagcount[tag]) > mincount ):
size = "smallTag"
elif ( (int)(tagcount[tag]) == mincount ):
size = "smallestTag"
tagcloud.append( "<a href='%s' class='%s' alt='There are %s entries tagged %s'>%s</a>\n" % ( '%s%s' % ( tagurl,tag ), size, str(tagcount[tag]), tag, tag ) )
if untagged:
tagcloud.append("<br/>")
tag = "untagged"
size = "mediumTag"
tagcloud.append( "<a href='%s' class='%s' alt='There are %s entries tagged %s'>%s</a>\n" % ( '%s%s' % ( tagurl,tag ), size, str(tagcount[tag]), tag, tag ) )
tagcloud.append("</div>")
result = "".join(tagcloud)
return result