Tag Cloud Custom Control


Qualche settimana fa, mentre preparavamo la struttura del nostro nuovo sito, abbiamo deciso di inserire in home page un box "Tag Cloud". Tutti sanno cos'è una Tag Cloud, non mi soffermerò quindi sui concetti di base; nel nostro caso, i termini evidenziati dovevano basarsi sui tag inseriti all'interno dei documenti pubblicati nel sito, sotto forma di "Notizie".
Per prima cosa, ho provato ad effettuare una ricerca sul web, ma le soluzioni trovate non mi soddisfacevano; troppo macchinose o non sufficientemente flessibili.
Così, ho dedicato qualche ora a pensare come ottenere un piccolo custom control, facilmente riutilizzabile, che fosse rapido da realizzare e modificabile nell'aspetto con il minimo sforzo. Il risultato, lo potete vedere nella tag cloud pubblicata sulla nostra home page.
 
Il database scaricabile cliccando sul link a fianco (box "Risorse") mostra il funzionamento della nostra Tag Cloud. Il sistema utilizza 5 elementi:

- il custom control tagCloudBox
- il form News
- le due viste (NewsActiveByDate) e (NewsActiveByTag)
- il foglio di stile tagCloud.css

tag cloudLa prima delle due viste, si limita ad elencare i documenti registrati usando il form News in ordine di data.

La seconda, è quella essenziale per il funzionamento del custom control: la prima colonna categorizza i documenti in base al contenuto del campo "Tags".

Importante, è la spunta sull'opzione "Show multiple values as separate entries"; in questo modo, ogni categoria nella vista mostra il nome di un Tag, ed il numero dei documenti sottostanti indica il numero di ripetizioni di un dato Tag



Nel Custom Control, sono definite 5 Custom Properties: Title, SourceView,  maxKeys, tagCount, tagStyles. La prima serve semplicemente per controllare il titolo del box, quello che nel nostro caso appare nella barra arancione. SourceView deve contenere il nome della vista da utilizzare per estrarre i tag; maxKeys serve per limitare il numero dei tag mostrati in elenco. Degli ultimi due, parleremo fra poco.

La lista dei tag è contenuta in un Repeat Control il cui script contiene il codice seguente:

var db:NotesDatabase session.getCurrentDatabase();
var sourceView:NotesView
db.getView(compositeData.SourceView);
var nav=ViewNavigator sourceView.createViewNav();
var n 0;
var tmpentry:ViewEntry;
var maxKeys compositeData.maxKeys;

//scorro l'elenco dei tag e li inserisco in un Vector--->>>
var keys new java.util.Vector();
var entry:NotesViewEntry nav.getFirst();
while (entry !null) {
  var text entry.getColumnValues().elementAt(0);
  keys.add(text+"["+entry.getChildCount().toString());

  tmpentry nav.getNextCategory();
  entry.recycle();
  entry tmpentry;
  n++;
}
//scorro l'elenco dei tag e li inserisco in un Vector---<<<

//elimino i tag dai meno ripetuti eccedenti maxKeys----->>>
if (n<=maxKeys){
  return keys;
}else{
  var x=0;
  while (keys.size()>maxKeys){
    indexPos keys.elementAt(0).indexOf("[",0);
    indexVal keys.elementAt(0).substr(indexPos+1);
    minPos 0;
    for(i=1;i<keys.size();i++){
      indexPos keys.elementAt(i).indexOf("[",0);
if (indexVal > keys.elementAt(i).substr(indexPos+1)){
        minPos=i;
        indexVal keys.elementAt(i).substr(indexPos+1);
      }
    }
    keys.removeElementAt(minPos);

    x++;
  }
  return keys;
}
//elimino i tag dai meno ripetuti eccedenti maxKeys-----<<<
il codice scorre tutte le categorie visibili nella vista ed inserisce in un Java Vector il nome di ogni Tag, agiungendovi il numero di ripetizioni, separato con una parentesi quadra. Se l'elenco contiene più risultati di quelli specificati nella Custom Property maxKeys, taglia i Tag eccedenti, partendo da quelli con meno ripetizioni.

Il Repeat Control contiene un unico elemento, un link la cui etichetta e stile sono definiti dai frammenti di codice seguenti:

classPos rowentry.indexOf("[",0);
rowentry.substring(0,classPos)+" ";

L'aspetto degli elementi è controllato tramite lo stile assegnato ad ognuno di essi. Per controllare ciascuno stile, ho utilizzato scipt seguente e le due Custom Properties "tagCount" e "tagStyles".
indexPos rowentry.indexOf("[",0);
indexVal rowentry.substr(indexPos+1);

for (i=0;i<compositeData.tagCount.length;i++) {
  if (indexVal <compositeData.tagCount[i]) {
    return compositeData.tagStyles[i];
  }
}
return compositeData.tagStyles[compositeData.tagCount.length -1];

Le due Custom Properties devono contenere due Array, nel nostro caso:
tagCount
tagStyles
var keys=new Array();
keys[0]="1";
keys[1]="2";
keys[2]="3";
keys[3]="4";
keys[5]="5";

return keys
var keys=new Array();
keys[0]="tag1";
keys[1]="tag2";
keys[2]="tag3";
keys[3]="tag4";
keys[5]="tag5";

return keys

Il codice assegnato alla proprietà Style dell'elemento Link estrae da ogni riga il numero di ripetizioni (parte della stringa a destra della parentesi quadra), confronta il numero con gli elementi dell'array a sinistra individuando la posizione del valore immediatamente <del numero di ripetizioni, ed estrae il nome dello stile da applicare prendendo l'elemanto corrispondente dall'array di destra. L'ultima riga dello script, fa in modo che nel caso il numero di ripetizioni di un tag fosse superiore all'ultimo valore dell'array di sinistra, a quest'ultimo verrebbe assegnato l'ultimo stile definito nell'array di destra.
Nel comporre i due array, bisogna soltanto rispettare un paio di condizioni:
- Il numero di elementi dell'array di destra deve essere >agli elementi di quello di sinistra
- nell'array di sinistra i "numeri" non devono necessariamente essere consecutivi, ma devono sempre essere inseriti dal più piccolo al più grande.

Infine, il foglio di stile tagCloud.css contiene gli stili definiti nell'array "tagStyles".

Questo è tutto, il database che potete scaricare dal box Risorse qui a fianco, contiene un piccolo esempio completamente funzionante. E' sufficiente installarlo su un server domino, firmare gli elementi con un ID appropriato ed aprire la pagina "http://<nome host>/<path>/ekntagcloud.nsf/tagCloud.xsp".
Un ultimo dettaglio: la Xpage contiene un secondo Custom Control, dall'aspetto molto spartano (sono un po' pigro...) inserito per dimostrare l'effetto di un click su uno dei Tag. All'elemento Link, infatti, non è assegnato alcun URL; il comportamento dipende dalle due semplici linee di codice javaScript (Server side) associate all'evento "OnClick", che provoca un Partial Refresh della pagina.

classPos rowentry.indexOf("[",0);
sessionScope.selectedTag=rowentry.substring(0,classPos)+" "

La variabile "selectedTag" è utilizzata dallo script di selezione relativo al Repeat Contol che visualizza i titoli delle news pubblicate, per filtrare i risultati della ricerca.
Un reload della pagina provoca un'annullamento di tutte le variabili session scope e dunque torna a fare apparire l'elenco completo delle notizie.

Bernardino
 
 

NAeS Consulting srl

via S.Senatore, 10
20122 Milano
p.IVA 04052980960

Informazioni commerciali

tel.: +39 02 45 48 72 63
fax: +39 02 70 04 66 85
e-mail: info@naes.it

Supporto tecnico

networking: support.networking@naes.it
software: suppsw@naes.it
help desk: https://helpdesk.naes.it