Forum OpenACS Development: Tagcloud

Posted by Ben Koot on
Is there a way to have the categories module spit out a an optional TagCloud?
2: Re: Tagcloud (response to 1)
Posted by Matthew Burke on
I took a look at this and I whipped some code together (I need to clean it up just a bit).  It works as follows: the input is the ID for a category tree, the proc generates a list of category_id, name and count---how many objects are mapped to that category, it then takes that list and generates an HTML fragment that looks as follows:

<div class="tagcloud">
  <a href="..." style="font-size: 25px;" class="tag">some tag</a>
  <a href="..." style-"font-size: 13px;" class="tag">another tag</a>

where the each link destination is the category page that lists all the objects mapped to that category and the size of the font is calculated by scaling the category's count between a min and max value (this will probably be more clear if I post the code).

So, I think it does what you want.

The big question I am grappling with is how exactly to deal with permissions.  It seems to me that there could be a wide range of different scenarios based on the permissions on the objects, the category trees, the user looking at the cloud, etc.

I'm having a similar conundrum trying to finish up some other code I'm working on---a 'du jour' service that generates an 'X of the day' link.

3: Re: Tagcloud (response to 1)
Posted by Ben Koot on
Great news. Thank's a lot


4: Re: Tagcloud (response to 1)
Posted by Matthew Burke on
Well, I installed the download package on my website, but when I tried to add an archive to it, it just barfed and I don't have time to debug it right now.

So for the time being, you can download and save it as packages/categories/tcl/tagcloud-procs.tcl.

The only public function can be called as

set tag_frag [category::tagcloud::tagcloud -tree_id $tree]

and will return an HTML fragment which represents the tag cloud.  As mentioned before, the links to the object browser are problematic because of permissions issues I haven't sorted yet.

But if you try it and send me feedback, I'll try and fix it <g>

5: Re: Tagcloud (response to 1)
Posted by Malte Sussdorff on
Can you submit your tagcloud code to CVS or tell me where I can retrieve it as the link does not work.

It is interesting and I think would make a nice addition to some of the sites we host.

6: Re: Tagcloud (response to 1)
Posted by Matthew Burke on

I suppose one of these days I should contact somebody and ask for cvs commit privileges. In the meantime, you can find the tcl code at

It's not very sophisticated, but hopefully it's useful. If there are modifications you would like me to make, let me know. And I'd be interested in any changes, extensions, fixes you make.


7: Re: Tagcloud (response to 1)
Posted by Malte Sussdorff on
You are about right that you'd face a permission problem, but I solved it before committing. Sadly now it takes a very long time to come up with the result:

select category_id, count(com.object_id), min(
from categories natural left join category_object_map com natural join category_trees
natural join category_translations trans
where tree_id = '1999' and trans.locale = 'en_US'
and exists (select 1 from acs_object_party_privilege_map ppm
where ppm.object_id = com.object_id
and ppm.privilege = 'read'
and ppm.party_id = '499')
group by category_id

HashAggregate (cost=498.47..498.47 rows=1 width=326)
-> Nested Loop (cost=0.00..498.46 rows=1 width=326)
-> Nested Loop (cost=0.00..497.37 rows=1 width=330)
Join Filter: ("inner".category_id = "outer".category_id)
-> Seq Scan on category_translations trans (cost=0.00..1.39 rows=1 width=322)
Filter: ((locale)::text = 'en_US'::text)
-> Nested Loop Left Join (cost=0.00..495.95 rows=3 width=12)
Filter: (subplan)
-> Seq Scan on categories (cost=0.00..1.39 rows=1 width=8)
Filter: (tree_id = 1999)
-> Index Scan using category_object_map_pkey on category_object_map com (cost=0.00..18.88 rows=6 width=8)
Index Cond: ("outer".category_id = com.category_id)
-> Nested Loop (cost=18.89..79.27 rows=1 width=0)
-> Hash Join (cost=18.89..69.23 rows=1 width=4)
Hash Cond: ("outer".grantee_id = "inner".party_id)
-> Nested Loop (cost=0.00..50.25 rows=15 width=8)
-> Seq Scan on acs_privilege_descendant_map pdm (cost=0.00..3.65 rows=1 width=168)
Filter: ((descendant)::text = 'read'::text)
-> Index Scan using acs_permissions_privilege_idx on acs_permissions p (cost=0.00..46.41 rows=15 width=176)
Index Cond: (("outer".privilege)::text = (p.privilege)::text)
-> Hash (cost=18.88..18.88 rows=6 width=4)
-> Index Scan using party_member_member_idx on party_approved_member_map pamm (cost=0.00..18.88 rows=6 width=4)
Index Cond: (member_id = 499)
-> Index Scan using acs_object_context_index_pk on acs_object_context_index c (cost=0.00..10.01 rows=2 width=4)
Index Cond: ((c.object_id = $0) AND (c.ancestor_id = "outer".object_id))
-> Seq Scan on category_trees (cost=0.00..1.07 rows=1 width=4)
Filter: (1999 = tree_id)
(28 rows)
8: Re: Tagcloud (response to 1)
Posted by Malte Sussdorff on
Is there a nice CSS which we should import into our blank-master.css to use for the tagclouds?
9: Re: Re: Tagcloud (response to 8)
Posted by Matthew Burke on

I don't have CSS for this (and nobody would be happy with anything I came up with---I have the style-sense of a slug).

I just threw the two classes (tagcloud and tag) in as hooks in case somebody else wanted to develop something.