PHP: un datagrid XHTML valido con paginazione per applicazioni web

Esempio di datagrid
Esempio di datagrid

Questo datagrid è un aggiornamento di quello presentato in questo post. Ho apportato alcune sostanziali modifiche per renderlo più flessibile ed accessibile, pur mantenendo le stesse prerogative che mi ero imposto inizialmente.
La modifica più urgente era quella di implementare un sistema di paginazione. Questo ha comportato inevitabilmente il cambiamento della modalità di passaggio dei dati al costruttore della classe. Mentre prima era sufficiente fornire il riferimento al risultato di una query, adesso è necessario passare il link alla connessione, il nome del database ed infine la query in formato stringa.

Le caratteristiche iniziali, che sono state ulteriormente migliorate, sono:

  • XHTML valido
  • Personalizzabile tramite fogli stile CSS
  • colonna aggiuntiva di link per azioni tipo “modifica”
  • Aspetto gradevole e alternanza di colorazione delle singole righe
  • Compatibile sia con PHP4 che con PHP5

Le nuove caratteristiche:

  • Semplice sistema di paginazione nel <tfoot> della tabella. Il numero di record per pagina da visualizzare vengono impostati come parametro del costruttore, default=0
  • Autoriconoscimento della o delle chiave primarie. Nel caso in cui l’autoriconoscimento fallisca, è possibile impostarle manualmente come parametro del costruttore
  • Il link nella colonna aggiuntiva può contenere una querystring, in questo caso il link alla chiave primaria viene appeso con “&” altrimenti con “?”
  • Possibilità di utilizzare il datagrid in una pagina che già contiene una querystring. In questo caso è necessario passare la querystring esistente come parametro al costruttore.
  • Possibilità di impostare numerose proprietà dei tag HTML

I parametri del costruttore:

  1. $link (obbligatorio) – riferimento alla connessione al db
  2. $db (obbligatorio) – stringa con il nome del database
  3. $query (obbligatorio) – stringa contentente la query di tipo SELECT
  4. $recPerPage=0 – Numero di record per pagina. Default=0 (tutti i record senza paginazione)
  5. $pk = NULL – Nome della chiave primaria (se più di una, separate da virgola) da immettere manualmente, se NULL (default) il riconoscimento è automatico
  6. $qs = NULL – Stringa contenente l’eventuale querystring associata alla pagina in cui viene pubblicato il datagrid.
Elenco dei metodi:
NomeTipoDefaultNote
setPkIsVisible()booleanfalseDetermina se le colonne relative alla chiave primaria sono visibili o no
setLinkPage()stringNULLImposta il link alla pagina da richiamare per le modifiche (Riferimento alla chiave primaria). Se NULL, la colonna aggiunitva non viene visualizzata.
setLinkLabel()string“Edit”Imposta il testo da visualizzare nella colonna dei link. Può contenere codice HTML per caricare un’icona.
setLinkTitle()string“Edit”Imposta il titolo del tag <a> nella colonna dei link.
setPrev()string“prev”Imposta il testo da visualizzare per la paginazione indietro. Può contenere codice HTML per caricare un’icona.
setNext()string“next”Imposta il testo da visualizzare per la paginazione in avanti. Può contenere codice HTML per caricare un’icona.
setSummaryTable()string“Data table”Imposta il testo per la descrizione “summary” della tabella.
setCaptionTable()string“Table”Imposta il testo per l’intestazione della tabella.
makeTable()Stampa la tabella

Un esempio di utilizzo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Database connection params
$host = 'localhost';
$user = 'root';
$password = '';
$database = 'prova';
$query = 'select * from es_libri';
// open the connection to the db server
$link = mysql_connect($host,$user,$password);
include ('datagrid.class.php');
// datagrid class with some options
$mydatagrid = &amp; new datagrid($link,$database,$query,3); // 3 rec per page
$mydatagrid-&gt;setLinkPage("test.php");
$mydatagrid-&gt;setLinkLabel("<img src="./mod.gif" alt="edit" />");
$mydatagrid-&gt;setLinkTitle("edit");
$mydatagrid-&gt;setPrev("<img src="./prev.gif" alt="previous" />");
$mydatagrid-&gt;setNext("<img src="./next.gif" alt="next" />");
$mydatagrid-&gt;setPkIsVisible(true);
$mydatagrid-&gt;setSummaryTable("Elenco dei libri in biblioteca del settore informatica");
$mydatagrid-&gt;setCaptionTable("Elenco libri informatica");
$mydatagrid-&gt;makeTable();

Per vedere l’esempio, cliccare qui.
Questo, invece è il pacchetto contenente la classe, il file di esempio, il foglio stile, le gif e l’sql per la creazione della tabella “es_libri”, (da creare in un db chiamato “prova”).

Note:

Per quanto abbia fatto diverse prove, non posso dire di aver coperto tutti i possibili errori, fate qualche prova prima di metterlo in produzione!.

Conclusioni:

Per il futuro mi riprometto di aggiungere la caratteristica di autoriconoscimento dei tipi dei campi e la formattazione automatica con allineamento a destra per i numeri

Riferimenti ed approfondimenti:

Javascript e CSS per la stampa di record selezionati in una tabella: l’approccio unobtrusive

Il rinoceronte: simbolo di javascriptHo trovato nel web questo codice javascript per la stampa selettiva di record che possono essere selezionati da una tabella HTML. L’idea è senz’altro interessante e utile, ma non segue la filosofia unobtrusive. Ho cercato di modificarlo seguendo la logica del progressive enhancement.

La regola principale per scrivere codice javascript non intrusivo, banalmente, è pensare che non venga eseguito…! E’ necessario cambiare il punto di vista, pensare che la presentazione della pagina HTML sia sufficiente a sé stessa con il solo ausilio di una progettazione coerente e dell’uso dei CSS. Il codice javascript, servirà soltanto ad integrare le funzionalità offrendo optional ai quali sia possibile rinunciare.
Lo script in questione permette di selezionare attraverso una checkbox una o più righe di una tabella e di stampare, utilizzando l’attributo CSS @media print solo le righe selezionate. Vediamo, dunque, perché non è unobtrusive: se il supporto javascript è disabilitato o comunque non disponibile, la tabella non verrà mai stampata. Questo succede perché gli elementi <tr> della tabella appartengono per default alla classe DONTPrint nella quale la proprietà display è impostata a none. La funzione javascript select_row() provvede a runtime lo scambio della classe di appartenenza dell’elemento <tr> da DONTPrint a DOPrint, che non essendo definita, per default mostra i contenuti.

La logica del progressive enhancement ci fa pensare invece che, non avendo la possibilità di stampare solo i record selezionati, sia almeno disponibile la stampa dell’intera tabella.
Ecco come impostare la pagina secondo questo approccio:

  1. Assegnamo a tutti gli elementi <tr>, per default la classe DOPrint
  2. Al caricamento del documento, mediante una funzione javascript scambiamo la classe dei <tr>, da DOPrint a DONTPrint
  3. Mediante la funzione select_row() ridefiniamo DOPrint solo le righe selezionate

Un po’ di codice:

1
2
3
4
5
6
7
8
9
<!-- Definizione del css per la stampa -->
<style type="text/css">
<!--
@media print {
 .DONTPrint { display:none; }
 .DONTEverPrint { display:none; }
}
-->
</style>

Le due funzioni principali javascript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- ... -->
<script type="text/javascript">
 
<!--
// Funzione lanciata in avvio
function init(){
 var myTableRows = document.getElementsByTagName("tr");
  for (i = 0; i < myTableRows.length; i++) {
    if(myTableRows[i].className=='DOPrint'){
     myTableRows[i].className = 'DONTPrint';
    }
  }
}
// Funzione per la selezione della riga
function select_row(row, color) {
 if (row.value=='on'){
 row.value="off";
 row.parentNode.parentNode.style.backgroundColor = color;
 row.parentNode.parentNode.className = 'DOPrint'
 }
 else{
 row.value="on";
 row.parentNode.parentNode.style.backgroundColor = '';
 row.parentNode.parentNode.className = 'DONTprint'
 }
}
// -->
</script>

Il codice HTML per l’avvio:

<body onload="init()">

Il codice HTML per la definizione delle righe della tabella:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- ... -->
<tr onmouseover="mouseover(this,'#cc6600','#cc6600');"
  onmouseout="mouseout(this,'#000000','#000000')"
  class='DOPrint'>
 
<td><input type="checkbox" class='DONTEverPrint'
  name="checkbox1" onclick="select_row(this, '#cccccc');">
</td>
<td>Arnold </td>
<td>M</td>
<td>45</td>
 
</tr>
<!-- ... -->

Una demo dell’intero esempio è disponibile qui

Con l’occasione, ho anche modificato sia l’HTML che il codice javascript dell’esempio per renderlo un poco più vicino alle direttive degli standard W3C. Probablimente questo codice è stato scritto qualche anno fa, quando ancora, purtroppo, la sensibilità dei programmatori in tal senso era piuttosto scarsa.

Conclusioni:

L’utilizzo di un approccio unobtrusive è utile non soltanto per matenere struttura e presentazione della pagina nei rispettivi ambiti, ma anche per acquisire una forma mentis in grado di pensare preventivamente le vere necessità dell’utente, le caratteristiche di base dell’applicazione e gli elementi facoltativi. Infine si può affermare che “pensare unobtrusive” vuole dire in qualche modo aver compreso meglio il funzionamento delle tecniche utilizzate.

Riferimenti ed approfondimenti:

La tecnologia usata nel sito della Fondazione Giannino Bassetti

Anteprima del sito FGBIn collaborazione con il collega Alessandro Scoscia, abbiamo lavorato alla ristrutturazione tecnologica del sito web della FGB. Abbiamo concentrato maggiormente gli sforzi verso l’aderenza agli standard W3C e l’usabilità, ottenendo per il momento, anche un buon grado di accessibilità. Il sito si basa su una piattaforma multi-blog “motorizzata” Movable Type. Il sito è visibile a questo indirizzo: www.fondazionebassetti.org.
Un’ampia documentazione delle tecniche utilizzate e degli hack messi in opera sono consultabili all’indirizzo: www.fondazionebassetti.org/it/rfc/