paolo@bimodesign.com | +34 608 61 64 10

JS / Ajax / Jquery / Json

        

Google Chart: Inserire piu' grafici sulla stessa pagina

In questo articolo vi illustro come implementare le Charts di Google, con la particolarita' di visualizzare piu' grafici sulla stessa pagina. Per la documentazione ufficiale, vi rimando al relativo link ufficiale, mentre qui vediamo nel dettaglio il processo,cominciando da come vengono archiviati i dati e come poi visualizzati.

L'articolo sara' diviso nei seguenti punti
- Archiviazione dei dati (db MySql)
- Lettura e normalizzazione dei dati (via JQuery/Json)
- Visualizzazione dei grafici (via JS)

Mentre non fa parte di questo articolo, la parte del codice che esegue la scelta dei dati, anche se nell'esempio che lascio on-line, potete verificarne il funzionamento.
Iniziamo dalla demo dove faccio notare che non ho inserito alcun foglio di stile CSS. Insomma, non e' proprio il massimo dal punto di vista grafico ;)

I dati
In questo caso, non vi illustro, per questioni di copyright e perche' mi dilungherei troppo, il disegno del DB, ma solo come ho archiviato, in un campo di tipo MEDIUMTEXT i dati che verranno estratti e quindi mostrati nei grafici.
Il formato in cui sono archiviati dati e' JSON ed un esempio e' questo.

{"eta":{"da 0 a 19":"33","da 20 a 44":"67","da 45 a 54":"9","da 55 a 64":"3","da 65 a ...":"3","Otros":"24"},"sesso":{"Hombres":"40","Mujeres":"26","Otros":"41"},"terminale":{"ALCATEL ALCATEL OT363":"1","LG LG KU990":"2","NOKIA NOKIA 2220":"1","NOKIA NOKIA 2610":"1","NOKIA NOKIA 2680":"1","NOKIA NOKIA 2730 CLASSIC":"2","NOKIA NOKIA 5310":"1","NOKIA NOKIA 6085":"1","NOKIA NOKIA 6120":"1","NOKIA NOKIA E61":"1","NOKIA NOKIA N73":"1","Otros":"83","RIM BLACKBERRY 8520":"1","SAMSUNG SAMSUNG C3050":"1","SAMSUNG SAMSUNG L760V":"1","SHARP SHARP TQ-GX17":"1","SHARP SHARP TQ-GX29":"1","SONY ERI SONY-ERICSSON W205":"3","TCT VODAFONE 541":"1","ZTE VODAFONE 547":"1","ZTE VODAFONE INDIE":"1"},"sistema operativo":{"android":"1","Otros":"106"}}


Potete notare che sono presenti 4 insiemi di dati (eta', sesso, terminale, sistema operativo) ed ogni insieme/array contiene il dettaglio dei dati che e' variabile. Questo e' uno dei motivi per il quale uso JSON. L'altro e' perche' e', insieme a XML, il formato piu' usato per lo scambio dei dati.
Come appunto noteremo qui in seguito.
Altro particolare da notare, che gli insiemi possono essere diversi in numero e tipo a seconda della statistica effettuata e quindi questo crea una ulteriore complessita' al problema.
Dopo aver visto come sono archiviati i dati, vediamo come li leggiamo

Lettura e normalizzazione dei dati
Come potete vedere nella demo, solo dopo la terza scelta, vengono visualizzati le "torte" dei grafici e quindi, solo in questo momento, via AJAX leggiamo i dati dal db e li dobbiamo restituire alla pagina principale.
Questo il codice della pagina principale, dove facciamo la call AJAX, alla url ajaxShowReport.php a cui passiamo come parametri, in POST, il nome della combo HTML e l'id (questo per poter uniformare la funzione PHP che eseguira' la select per estrarre i dati per tutte le scelte effettuate.

case "listreportstatisticdetail":
      $("#datafinal").show();
              
      $.ajax({ 
          type: "POST", 
          url: "ajaxShowReport.php", 
          data:{combo:$(this).attr("name"),
                   id:$(this).val()},
             dataType: "text", 
             success: function(data){
                              drawChart(jQuery.parseJSON(data));
                    }});
            break;

Da notare che il ritorno della chiamata AJAX, viene passato, come input, alla funzione JS drawChart() della API di Google Chart. Il valore di "data", che vi ricordo presenta il formato JSON illustrato in precedenza, viene appunto parseato per essere poi letto da JS.
Evito di descrivere il codice della pagina ajaxShowReport.php, perche' non e' semplicissimo, cosi' come la select per estrarre i dati.

La creazione delle Chart
Nel mio caso, come potete notare dalla demo, ho utilizzato i grafici a torta, ma Google mette a disposizione varie scelte, per le quali vi rimando alla documentazione ufficiale indicata all'inizio dell'articolo. Inoltre, non mi soffermero' a spiegare tutto il codice della api di Google, ma solo i punti piu' interessanti per permettere la creazione di n-grafici.
L'idea e' quella di creare un grafico per ogni insieme (eta', sesso, terminale, sistema operativo) e quindi inserire i relativi dati.
Essendo gli insiemi variabili in numero e tipo di report, ho e' stato necessario trovare un algoritmo per uniformare il codice a tutte le possibilita'. E questo e' un estratto del mio codice, basato chiaramente su quello che mette a disposizione google.
Questo il codice e di seguito inserisco la spiegazione di parte del codice.

google.load('visualization', '1.0', {'packages':['corechart']}); 
google.setOnLoadCallback(drawChart); 
      
function drawChart(datos) { 
   console.log(datos);   
   var ind;
   var data;
   var options;
   var chart;
   var elementos;
        
   // first level
   for(var titlechart in datos ){
      ind = 0;           
      data = new google.visualization.DataTable();
            
      data.addColumn('string', 'Topping'); 
      data.addColumn('number', 'Slices'); 

      elementos=countProperties(datos[titlechart]);
            
      data.addRows(elementos);
            
      options = {'title': titlechart, 
                 'width':400, 
                'height':300}; 
      
      // second level      
      for( var titledetail in datos[titlechart] ){
         data.setCell(ind, 0, titledetail);
         data.setCell(ind, 1, parseInt(datos[titlechart][titledetail]));
 
        ind=ind+1;   
      }

      chart = new google.visualization.PieChart(document.getElementById('chart_div_'+titlechart)); 
      chart.draw(data, options);
  }
} 

Visto che abbiamo i dati gia' formattati da JSON, come array (ovvero object), il ciclo per la lettura del primo e del secondo livello, sara' un semplice for.
La API di Google richiede che per definire l'array dei dati (data)che sara' l'input al metodo chart.draw, occorra innanzitutto definir il numero esattodegli elementi da visualizzare.
Per calcolare questo valore ho usato la funzione

countProperties(datos[titlechart]);
...
...
// Dichiarazione 
function countProperties(obj) {
   var count = 0;
 
   for(var prop in obj) {
     if(obj.hasOwnProperty(prop))
        ++count;
   }

   return count;
}   

Notare l'uso della funzione JS hasOwnProperty() per calcolare il numero degli elementi dell'object.
Definito quindi il numero degli elementi che conterra' l'array dei dati, passiamo ad inserire i dati, attraverso questo semplice ciclo for

for( var titledetail in datos[titlechart] ){
    data.setCell(ind, 0, titledetail);
    data.setCell(ind, 1, parseInt(datos[titlechart][titledetail]));
 
    ind=ind+1;   
}

L'API di Google richiede che il formato sia di questo tipo, ovvero, nome e valore (anche in questo caso ci sono delle opzioni supplementari, ma vi lascio alla documentazione ufficiale.

data.addRows([
          ['Mushrooms', 3],
          ['Onions', 1],
          ['Olives', 1],
          ['Zucchini', 1],
          ['Pepperoni', 2]
        ]);


Quindi il ciclo for dovra' inserire per ogni valore due elementi. A posizione "0" il nome dell'elemento e il valore. Nel mio caso, visto che sono tutti valori interi, e' stato necessario fare un cast a "int".