Documentazione Grules, versione 2.1


Demografia: un'applicazione statistica

Files necessari

Funzionamento

L'applicazione permette di visualizzare sulla mappa una serie di indicatori demografici (vecchiaia, immigrazione etc) specificando l'anno. Selezionando l'indicatore viene mostrata una legenda che associa valori numerici ai colori sulla mappa.

<script>

var anno = 2010;
var indicatore = "vecchiaia"

$(function() {
  var demografia = {
    id: "demografia",
    control: { ejs: "demografia/control.ejs" },
    format: "mjson",
    geometry: { url: "coperture/comuni/" },
    style: { 'default':   { strokeColor: "#888", strokeWidth: 1, fillOpacity: 0.6},
           'select':    { fillColor: "#cc0" },
           'temporary': { fillColor: "#dd0" } }, 
//    stylemap: "demografia/list.jsp&anno=<%=anno%>&indicatore=<%=vecchiaia%>",
    info: { url: "demografia/info.jsp?comune_istat=<%=id%>&indicatore=<%=vecchiaia%>" }
    legend: { url: "demografia/legend.ejs" }
  }
});




</script>

control.ejs

Per consentire all'utente di scegliere la combinazione di indicatore, anno, creiamo una <form> nella legenda:

legend: function() {
 var legend =
"    <h3><a href=''>Demografia in Toscana</a></h3> " +
"    <form id='form'>"+
"    <h4>Seleziona l'indicatore</h4>"+
"    <select name='indice' id='indice'>"+
"      <option value='vecchiaia'>Indice di vecchiaia   </option>" +    
....
"    <h3>Legenda</h3>" + 
"    <div id='legenda'></div>";

Usando jQuery associamo l'evento onChange a ciascuna select alla funzione updateView (definita in seguito)

    $('#indice').change(updateView);
    $('#anno').change(updateView);
    updateView();

Stili

Per colorare le mappe useremo la funzione loadStyleMap di Layer, che carica da un url un file JSON che associa uno stile a ciascuna area usando il valore di un'attributo. Nel nostro caso il file JSON viene generato da list.jsp (che sarà quindi il nostro url) e l'attributo è id.

list.jsp ritorna, per ogni combinazione di indice, e anno un file JSON formattato così

{"default": { 
  "045": { "fillColor": "#66B866" },
  "046": { "fillColor": "#66B866" },
  "047": { "fillColor": "#CCE7CC" },
  "048": { "fillColor": "#66B866" },
  "049": { "fillColor": "#66B866" },
  "050": { "fillColor": "#CCE7CC" },
  "051": { "fillColor": "#CCE7CC" },
  "052": { "fillColor": "#66B866" },
  "053": { "fillColor": "#66B866" },
  "100": { "fillColor": "#CCE7CC" }
}

Nell'esempio 045 è il codice istat della provincia; Nel nostro caso, visto il numero di combinazioni, list.jsp crea questi files facendo una query su db, ma potremmo anche precalcolarli tutti e salvarli su files statici.

updateView

Questa funzione aggiorna la mappa quando vengono dalla legenda si cambia un parametro, analizziamola in dettaglio.

function updateView() {
 $('#info').css('display', 'none');

La prima cosa che facciamo è nascondere l'info quando si cambia un parametro

 
 for(var i in demografia.vectors) {
   demografia.vectors[i].setVisibility(false);
   demografia.vectors[i].clear();    
 }

Rendiamo invisibili tutti i layers (basterebbe farlo sul layer attualmente visibile, ma siamo pigri. NOTA: anche qui si potrebbe incapsulare meglio il codice... stesso discorso di prima.

 var anno = $('#anno').val();
 var indice = $('#indice').val();
 var aggregato = $('#aggregato').val();
 var url = "/wizgrule/webstat/demografia/list.jsp?anno="+anno+"&indice="+indice+"&aggregato="+aggregato;

Qui leggiamo i tre parametri e costruiamo l'url da passare a loadStyleMap

 if(indice == 'stranieri' && Number(anno) < 2002) {
   alert("Dato non disponibile.");
 } else {
   var layer = demografia.vectors[aggregato];
   layer.loadStyleMap(url, keys[aggregato], function() { layer.setVisibility(true); });
 }

Per l'indice stranieri i dati sono parziali... altrimenti carichiamo il nuovo stile. NOTA: il layer viene reso visibile DOPO aver caricato lo stile, per evitare di mostrarlo prima con i colori vecchi e poi con quelli nuovi, generando un fastidioso sfarfallio

 if(aggregato == 'Prov' || aggregato == 'Apt' || aggregato == 'Asl')
   $('#legenda').load('demografia/legenda_province.html #' + indice);
 else 
   $('#legenda').load('demografia/legenda_comuni.html #' + indice);
}

Infine mostriamo il pezzo i legenda corrispondente all'aggregato e all'indice corrente: se l'indice è vecchiaia viene caricato da legenda_province.html il codice html all'interno di

<div id="vecchiaia">

Highlight e select

Infine configuriamo il comportamento dell'applicazione quando l'utente passa il mouse su un'area o ne seleziona una tramite le funzioni highlighted e selected

Highlight

highlighted: function(event) {
   var aggregato = $('#aggregato').val();
   var feature = event.feature;
   var handler = event.object.handlers.feature;
   var aggregato = $('#aggregato').val();
   $('#detail').html(feature.attributes[names[aggregato]]);
   $('#detail').css('left', handler.evt.xy.x + 10 + 'px');
   $('#detail').css('top', handler.evt.xy.y + 10 + 'px');
   $('#detail').css('display', 'block'); 
 },

Quello che vogliamo è mostrare il nome dell'area, sia essa provincia, comune etc. Siccome il l'attributo da usare è diverso a seconda della copertura, (es. nome per le province, nomemin per i comuni etc.) ci siamo salvati le corrispondenze nella variable names:

var names = { 'Prov':'nome', 'Comune':'nomemin', 'Asl':'asl_descr', 'Apt':'az_prom_tu', 'Zd':'asl_zona', 'Sel':'descrizion' };

feature.attributes[names[aggregato]] contiene il nome dell'area

Select

selected: function(event) {
   var feature = event.feature;
   var aggregato = $('#aggregato').val();
   var indice = $('#indice').val();
  
   Overlay.loadInfo('/wizgrule/webstat/demografia/info.jsp?id='+feature.attributes[keys[aggregato]]+
   '&aggregato='+aggregato+'&nome='+escape(feature.attributes[names[aggregato]]) +
   '&indice='+indice);
  },

L'info viene generato dinamicamente dalla pagina info.jsp che ha bisogno come parametri dell'aggregato, dell'indice, del nome dell'area e dell'identificativo dell'area.

Come visto sopra nome e identificativo dipendono dall'aggregato e la corrispondenza è salvata nelle variabili keys e names

Piccoli tocchi finali

Il file legenda_province.html usa un foglio di stile: color.css. La funzione di jQuery che carica pezzi di html, non carica i fogli di stile associati, per cui lo faremo noi usando un'altra funzione jQuery

$("head").append("");
css = $("head").children(":last");
css.attr({
  rel:  "stylesheet",
  type: "text/css",
    href: "demografia/colors.css"
});

NB: sarebbe meglio cancellare dal file le funzioni info detail e hideDetail che non vengono più usate.