Attenzione! Questo contenuto è vecchioQuesto articolo risale al 2009, quindi i contenuti e le operazioni qui consigliate potrebbero essere diventate obsolete nel corso del tempo.

Quello che vedete sulla destra di questo sito è un calendario particolare, nel senso che è progettato per il funzionamento asincrono tramite ajax. In questa maniera si può facilmente integrare un modulo calendario in qualsiasi sito con pochissime modifiche e separando nettamente la parte "intelligente" del programma, cioè la creazione dei giorni a partire da un dato mese/anno, dalla parte "meno intelligente", quella di output verso il browser.

Ecco quindi spiegato il funzionamento, separato in:

  • Script PHP Server-Side che crea l'xml con i dati del mese/anno
  • Script client-side in Javascript per iniettare il markup del calendario verso il browser
  • Un esempio di markup HTML per rendere funzionante il tutto

Codice PHP server-side (Creazione dell'xml della coppia mese/anno richiesta)

<?php
	$mese = $_GET['month'];
	$anno = $_GET['year'];
	
	$primoGiornoMese = date( "w", mktime (0, 0, 0, $mese, 1, $anno) );
	
	if( $primoGiornoMese != 1 ) {
		if( $primoGiornoMese == 0 ) $counter = 6;
		else $counter = $primoGiornoMese - 1;
		
		if( $mese == 1 ) { $vecchioMese = 12; $vecchioAnno = $anno - 1; } else { $vecchioMese = $mese -1; $vecchioAnno = $anno; }
		
		$giorniMesePrecedente = date( "t", mktime(0, 0, 0, $vecchioMese, 1, $vecchioAnno) );
		for($i = $counter - 1; $i >= 0; $i--) {
			$curr = mktime(0, 0, 0, $vecchioMese, $giorniMesePrecedente - $i, $vecchioAnno);
			$tArr = Array('mod' => 'oldmonth', 'day' => $giorniMesePrecedente - $i, 'changeRow' => false);
			$calendario[] = $tArr;
		}
	}
	
	$curr = mktime(0, 0, 0, $mese, 1, $anno);
	$continua = true;
	$k = 0;
	while( $continua ) {
		$flagStile = $cambiaRiga = false;
		
		$giornoCorrente = date( "w", $curr );
		$numeroCorrente = date( "d", $curr );
		if( $curr == mktime(0, 0, 0, date("m"), date("d"), date("Y")) ) $flagStile = 'currentDay';
		else {
			if( $giornoCorrente != 6 && $giornoCorrente != 0 ) $flagStile = 'normalDay';
			else $flagStile = 'weekendDay';
		}
		
		if( $giornoCorrente == 0 ) $cambiaRiga = true;
		
		$tArr = Array('mod' => $flagStile, 'day' => $numeroCorrente, 'changeRow' => $cambiaRiga);
		$calendario[] = $tArr;
		
		$curr = mktime(0, 0, 0, $mese, date("d", $curr) + 1, $anno);
		
		if( date("m", $curr) > $mese || ( date("m", $curr) == 1 && $mese == 12 ) || $k >= 50) $continua = false;
		$k++;
	}
	$giorniCodestoMese = date("t", mktime(0, 0, 0, $mese, 1, $anno));
	if( ( $giornoFinaleMese = date("w", mktime(0, 0, 0, $mese, $giorniCodestoMese, $anno)) ) != 0 ) {
		for($i = 1; $i <= (7 - $giornoFinaleMese); $i++) {
			$tArr = Array('mod' => 'oldmonth', 'day' => $i);
			$calendario[] = $tArr;
		}
	}
	
	header('Content-Type:text/xml');
	echo '<?xml version="1.0" encoding="UTF-8" ?>' . chr(10);
	echo '<root>' . chr(10);
	echo '<monthInfo><month>' . substr( ucfirst(itdate("F", mktime(0, 0, 0, $mese, 1, $anno))), 0, 3 ) . '</month><year>' . $anno . '</year></monthInfo>' . chr(10);
	
	foreach( $calendario as $giorno => $valoriGiorno ) {
		$mod = $valoriGiorno['mod'];
		$day = number_format($valoriGiorno['day'], 0, "", "");
		$alt = $valoriGiorno['alt'];
		$title = $valoriGiorno['title'];
		$link = $valoriGiorno['link'];
		$changeRow = ( $valoriGiorno['changeRow'] == false ) ? 0 : 1;
		
		echo '<giorno mod="' . $valoriGiorno['mod'] . '" day="' . number_format($valoriGiorno['day'], 0, "", "") . '" changeRow="' . $changeRow . '"></giorno>' . chr(10);
	}
	echo '</root>' . chr(10);
	
	function itdate ($date_format="l j F Y - H:i:s", $time=0) {//, $date_format="l j F Y - H:i:s", $lang=it 

		$hourdiff = "0";
		$timeadjust = ($hourdiff * 60 * 60);

		if (! $time) $time = time()+$timeadjust;
		if (! $lang) $lang = "It";
		if (! $date_format) 
		{ 
			$date_format = "l j F Y - H:i:s"; 
		}

		$week_days_long = array('Sunday' => 'Domenica', 'Monday' => 'Lunedì ', 'Tuesday' => 'Martedì',
			'Wednesday' => 'Mercoledì', 'Thursday' => 'Giovedì', 'Friday' => 'Venerdì',
			'Saturday' => 'Sabato');
		$months_long = array('January' => 'Gennaio', 'February' => 'Febbraio',
			'March' => 'Marzo', 'April' => 'Aprile','May' => 'Maggio', 'June' => 'Giugno',
			'July' => 'Luglio', 'August' => 'Agosto', 'September' => 'Settembre',
			'October' => 'Ottobre', 'November' => 'Novembre', 'December' => 'Dicembre');
		$week_days_short = array('Sun' => 'Dom', 'Mon' => 'Lun', 'Tue' => 'Mar', 'Wed'=>'Mer',
			'Thu' => 'Gio', 'Fri' => 'Ven', 'Sat' => 'Sab');
		$months_short = array('Jan' => 'Gen', 'Feb' => 'Feb', 'Mar' => 'Mar', 'Apr' => 'Apr',
			'May' => 'Mag', 'Jun' => 'Giu', 'Jul' => 'Lug', 'Aug' => 'Ago',
			'Sep' => 'Set', 'Oct' => 'Ott', 'Nov' => 'Nov', 'Dec' => 'Dic');

		$clock = date($date_format, $time);
		
		if(preg_match("/F/", $date_format) && ($lang != "En")) {
			$model = date("F", $time);
			$replace = $months_long[date("F", $time)];
			$clock = preg_replace("/$model/", $replace, $clock);
		}
		if(preg_match("/l/", $date_format) && ($lang != "En")) {
			$model = date("l", $time);
			$replace = $week_days_long[date("l", $time)];
			$clock = preg_replace("/$model/", $replace, $clock);
		}
		if(preg_match("/M/", $date_format) && ($lang != "En")) {
			$model = date("M", $time);
			$replace = $months_short[date("M", $time)];
			$clock = preg_replace("/$model/", $replace, $clock);
		}
		if(preg_match("/D/", $date_format) && ($lang != "En")) {
			$model = date("D", $time);
			$replace = $week_days_short[date("D", $time)];
			$clock = preg_replace("/$model/", $replace, $clock);
		}
		
		return strtolower($clock);
	}
?>

Codice Javascript per l'iniettamento del markup del calendario verso il browser

/* Calendar Handler JS client-side script v1.1 */

/* 

CONFIGURAZIONE:

Cambiare i valori delle variabili di configurazione, sapendo che:
_id_contenitore_calendario = ID del contenitore che andrà a contenere il calendario. E' un div che conterrà solo una tabella. SPECIFICARE IL # prima dell'id.
_id_contenitore_header_mese_anno = ID del contenitore che conterrà la coppia mese-anno sopra la tabella del mese.
_classe_cella_mesenoncorrente = classe css da applicare alle celle che NON sono del mese corrente, ma che mandiamo in output per completezza
_classe_cella_mesecorrente = classe css da applicare alle celle che sono del mese corrente
_classe_cella_weekend = classe css da applicare alle celle che sono sabato o domenica del mese corrente
_classe_cella_giornocorrente = classe css da applicare nel caso in cui una cella-giorno del calendario corrisponda al giorno corrente

ESEMPIO MARKUP HTML PER RENDERE FUNZIONANTE IL MODULO CALENDARIO: 
<div id="contenitore_tabella_calendario">
	<p id="header_tabella_calendario"></p>
	<table>
		<tbody></tbody>
	</table>
</div>

*/
	// Inizializzazione variabili
	_id_contenitore_calendario = '#contenitore_tabella_calendario';
	_id_contenitore_header_mese_anno = '#header_tabella_calendario';
	_classe_cella_mesenoncorrente = 'oldmonth';
	_classe_cella_mesecorrente = 'normalmonth';
	_classe_cella_weekend = 'weekendday';
	_classe_cella_giornocorrente = 'currentday';
	
	//Gestione Data Odierna
	var today = new Date();
	var mese = today.getMonth() + 1;
	var anno =  today.getFullYear();
	
	// Trigger delle funzioni da far partire all'avvio
	$(document).ready(function() {
		$.ajax({
			type: "GET",
			url: "xml_calendar_creator.php",
			data: "month=" + mese + "&year=" + anno,
			dataType: 'xml', 
			success: parseXmlCalendario, 
			error: function (a, b, e) {
				throw(e);
			}
		});
	});
	
	parseXmlCalendario = function(xml) {
		// Variabile della classe delle celle per la tabella del calendario
		var cellClass = "";
		
		// Iniettamento del titolo del calendario (Mese e Anno)
		$(_id_contenitore_header_mese_anno).html( $(xml).find('monthInfo month').text() + " " + $(xml).find('monthInfo year').text());
		
		// Iniettamento del codice html completo per il calendario
		
		var htmlCalendario = '<tr>';
		$(xml).find('giorno').each(function() {
			var mod = $(this).attr('mod');
			var giorno = $(this).attr('day');
			var cambiaRiga = $(this).attr('changeRow');
			
			switch ( mod ) {
				case 'oldmonth':
					cellClass = _classe_cella_mesenoncorrente;
					break;
				case 'normalDay':
					cellClass = _classe_cella_mesecorrente;
					break;
				case 'currentDay':
					cellClass = _classe_cella_giornocorrente;
					break;
				case 'weekendDay':
					cellClass = _classe_cella_weekend;
					break;
				default: break;
			}
			
			htmlCalendario +=  '<td class="' + cellClass + '" align="center">' + giorno + '</td>';
			if ( cambiaRiga == 1 ) htmlCalendario += '</tr><tr>';
		});
		htmlCalendario += '</tr>';
		
		$(_id_contenitore_calendario + ' tbody').html(htmlCalendario);
	}

Esempio di markup HTML per rendere il tutto funzionante

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<title>Prova</title>
	<script type="text/javascript" src="jquery.js"></script>
	<script type="text/javascript" src="calendar_js.js"></script>
</head>
<body>
	<div id="contenitore_tabella_calendario">
		<p id="header_tabella_calendario"></p>
		<table>
			<tbody></tbody>
		</table>
	</div>
</body>
</html>
Mischiare il tutto

Il codice PHP può essere salvato con un nome qualsiasi, solo bisogna ricordarsi di andare a modificare il file javascript e, sotto la parte di creazione della richiesta ajax, andare a modificare il nome della variabile che contiene le impostazioni della richiesta.

Ricordo che questo sistema implica forzatamente l'utilizzo della libreria jQuery per poter funzionare. E' chiaramente visibile nel terzo snippet di codice HTML, dove è specificato il richiamo del file jquery.js