Tag cloud with data from another application

For a project I needed a tag cloud to provide some alternative navigation to a view. Easy I thought; such control is part of the XPages extension library. However it turns out that this control does not support to use a view from another application/database as the data-source.

Some examples I found (1), (2), (3) required some work anyway so I wrote a quick prototype based upon the tag cloud component described in the OneUI documentation. The tag cloud is really simple but for now it does the job (as it appears). Here is the code.

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=”http://www.ibm.com/xsp/core”&gt;
<xp:panel tagName=”div” styleClass=”lotusTagCloud lotusChunk”
style=” overflow: hidden”>
<xp:text escape=”false” id=”txCloud”>
<xp:this.value><![CDATA[#{javascript:importPackage(java.util);

var viewPrefs: NotesView = database.getView(“$v-preferences”);
var docPrefs: NotesDocument = viewPrefs.getFirstDocument();
var serv = docPrefs.getItemValueString(“tx_server”);
var faqdb = docPrefs.getItemValueString(“tx_loc_faq”);

var db:NotesDatabase = session.getDatabase(serv,faqdb);
var vw:NotesView = db.getView(compositeData.vwSource);

var coll:NotesDocumentCollection = vw.getAllEntries();
var totalNum:Integer = coll.getCount();
var myNum:Integer;

var result:String = “”;

var ref = compositeData.ref;

var nav:NotesViewNavigator = vw.createViewNav();
var ve:NotesViewEntry = nav.getFirst();

//some calculation first…
var high:Integer = 0;
var low:Integer = 1000;
var max:Integer = 5;
while (ve != null) {

if (ve.isCategory()){
if (ve.getChildCount() > high){
high = ve.getChildCount()
}
if (ve.getChildCount() < low){
low = ve.getChildCount();
}
}

// Get the next entry and recycle the current one
var tmpentry = nav.getNext();
ve.recycle();
ve = tmpentry;
}

var range:Integer = high-low;
var factor:Integer = max*low;
var ceil:Integer = max-1;

//create cloud…
var nav:NotesViewNavigator = vw.createViewNav();
var ve:NotesViewEntry = nav.getFirst();

while (ve != null) {

if (ve.isCategory()){
cat=ve.getColumnValues().elementAt(0);
myNum=ve.getChildCount();
var myScore = Math.round(((ceil / range) * myNum) + (high – factor) / range);
result+=”<li><a class=’lotusF” + myScore + “‘ href='” + ref + cat + “‘>” + cat + “[” + myNum + “]</a></li>”
}

// Get the next entry and recycle the current one
var tmpentry = nav.getNext();
ve.recycle();
ve = tmpentry;
}

return “<ul>” + result + “</ul>”;}]]></xp:this.value>
<xp:this.attrs>
<xp:attr name=”role” value=”navigation”></xp:attr>
</xp:this.attrs>
</xp:text>
</xp:panel>
</xp:view>

Code walkthrough

The code resides in a custom control which uses 2 properties; one for the view to use as data-source and the link to use to redirect to. The links will direct to a page with a view that will be filtered by the ‘selected text’.

The code resides in an application that reads data from another NSF that does not contain any XPages code yet. In the project will deliver a new web interface for an existing Domino application and I wanted to avoid code collision. The ultimate goal would be to remove all the “old-spice” Domino code one day. So for now I have a preferences document where I store the location of the data-source application.

I go through the data-source view twice 😕 since the application does not have so many documents this is (still) acceptable. The values for the tags are calculated and at the end we write the values back to the screen. The CSS in the OneUI does the nice styling job.

Screenshot_2

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s