<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CescoBlog &#187; Coding</title>
	<atom:link href="http://www.cescopag.com/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cescopag.com</link>
	<description>Web-appunti tecnici (e non) per webdesigner e sviluppatori.</description>
	<lastBuildDate>Fri, 24 Dec 2010 08:11:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Google Maps API: &#8220;Calcola il percorso&#8221; nel nostro sito</title>
		<link>http://www.cescopag.com/2009/11/google-maps-api-calcola-il-percorso-nel-nostro-sito/</link>
		<comments>http://www.cescopag.com/2009/11/google-maps-api-calcola-il-percorso-nel-nostro-sito/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 21:05:40 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[directions]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=122</guid>
		<description><![CDATA[
Come molti di voi sapranno Google mette a disposizione per la maggior parte dei propri prodotti una serie di strumenti per sfruttarne le potenzialità nei nostri progetti.
  Google Maps non fa eccezione e ci fornisce tutti gli strumenti (API) per sfruttare le mappe di Google nei nostri siti tramite Javascript.


  Una delle funzionalità [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.cescopag.com/wp-content/uploads/2009/11/maps.jpg" alt="Google Maps Directions" title="Google Maps Directions" width="200" height="167" class="alignright size-full wp-image-130" /></p>
<p>Come molti di voi sapranno Google mette a disposizione per la maggior parte dei propri prodotti una serie di strumenti per sfruttarne le potenzialità nei nostri progetti.<br />
  <strong>Google Maps </strong>non fa eccezione e ci fornisce tutti gli strumenti (<strong>API</strong>) per sfruttare le mappe di Google nei nostri siti tramite Javascript.
</p>
<p>
  Una delle funzionalità più utili è quella di poter <strong>calcolare il percorso </strong>ottimale per raggiungere un determinato luogo, ottenendo tutte le indicazioni sulle svolte e sulle strade da percorrere. Non molti sanno che queste funzionalità sono a disposizione degli sviluppatori per integrarle nei propri progetti, ed è proprio ciò che faremo.
  </p>
<p><a href="http://www.cescopag.com/demos/directions/demo3.html" class="linkdemo" target="_blank">Demo</a></p>
<p><span id="more-122"></span></p>
<p>
  Ipotizziamo di voler integrare nel nostro sito una comoda sezione &#8220;Come raggiungerci&#8221;, dove l&#8217;utente possa inserire la propria posizione ed ottenere il percorso per raggiungerci.
  </p>
<p>
  La nostra pagina quindi sarà composta da un breve form dove l&#8217;utente inserirà la posizione, la mappa dove verrà visualizzato il percorso e l&#8217;area in cui verranno visualizzate le informazioni:</p>
<pre>
&lt;form name="findRoute" action=""&gt;
	&lt;p&gt;
		&lt;label for="partenza"&gt;Da dove parti?&lt;/label&gt;
		&lt;input type="text" name="partenza" /&gt;
	&lt;/p&gt;

	&lt;p&gt;
		&lt;input type="submit" value="Calcola" name="calcola" id="calcola" /&gt;
	&lt;/p&gt;
&lt;/form&gt;

&lt;div id="map"&gt;&lt;/div&gt;
&lt;div id="route"&gt;&lt;/div&gt;
</pre>
<p>Com&#8217;è facile intuire la mappà sarà inserita all&#8217;interno del div <em>map</em>, mentre le indicazioni all&#8217;interno del div <em>route</em>.</p>
<p>  Ma veniamo alla parte Javascript. Per prima cosa è necessario procurarsi una <strong>API Key </strong>dal sito google:
</p>
<p> <a href="http://code.google.com/intl/it-IT/apis/maps/signup.html">http://code.google.com/intl/it-IT/apis/maps/signup.html</a></p>
<p>Una volta ottenuta la chiave possiamo includere il javascript di Google Maps: </p>
<pre>
&lt;script src="http://maps.google.com/maps?file=api&#038;v=2.x&#038;key=CHIAVE" type="text/javascript"&gt;&lt;/script&gt;
</pre>
<p>Dove al posto di <em><strong>CHIAVE</strong></em> ci andrà la API Key fornita da Google.</p>
<p>Procediamo ora con lo script vero e proprio. Innanzitutto inizializziamo una serie di variabili vuote che conterranno gli oggetti di Google Maps che istanzieremo:</p>
<pre>
/* GOOGLE MAPS OBJECTS */
var home;       //Home GLatLng object
var map;        //GMap object
var directions; //Directions object
var marker;     //GMarker object
</pre>
<p>La prima funzione che andremo ad utilizzare sarà la funzione <code>initialize()</code> che come dice il nome preparerà tutto il necessario per far funzionare la mini-applicazione. Questa funzione dovrà essere richiamata al caricamento della pagina, ad esempio all&#8217;interno del tag <em>body</em>:</p>
<pre>
&lt;body onload="initialize()"&gt;
</pre>
<p>Ma veniamo al codice. Per prima cosa recuperiamo gli elementi html che ci servono tramite il metodo <code>document.getElementById</code>:</p>
<pre>
//Get html elements needed:
var mapPanel        = document.getElementById('map');
var directionsPanel = document.getElementById('route');
var submitButton    = document.getElementById('calcola');
</pre>
<p>Subito dopo invece definiamo il nostro punto base, nell&#8217;esempio sarà la nostra ipotetica sede:</p>
<pre>
//Home location:
home = new GLatLng(45.434629,12.337925);
</pre>
<p>Ora che abbiamo il necessario possiamo già istanziare la mappa che verrà visualizzata di default e mostrerà il punto base:</p>
<pre>
//Create a map:
map = new GMap2(mapPanel);
map.setCenter(home, 13);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
</pre>
<p>Per prima cosa viene creato l&#8217;oggetto <strong>GMap2</strong>, cioè la Google Map, e viene associato al <em>div#map</em> (mapPanel). La mappa viene poi centrata in home, al livello di zoom 13 (qui possiamo procedere a tentativi, più piccolo sarà il numero e più superficie terrestre vedremo). Tramite le altre due righe andiamo ad aggiungere i controlli che ci interessano (in questo caso i controlli standard e quelli per il tipo di visualizzazione &#8211; satellite, mappa, ibrida).</p>
<p>Ora dobbiamo evidenziare il punto base, e lo faremo aggiungendo un <em>marker</em>:</p>
<pre>
//Create marker:
marker = new GMarker(home);
map.addOverlay(marker);
</pre>
<p>Al marker possiamo aggiungere un fumetto descrittivo, contenente ad es. l&#8217;indirizzo, che si apre al click:</p>
<pre>
GEvent.addListener(marker, "click", function() {
    marker.openInfoWindowHtml("&lt;strong&gt;Venezia&lt;/strong&gt;&lt;br /&gt;Piazza San Marco");
});
</pre>
<p>Il comando <code>addListener</code> serve appunto per associare il click sul marker all&#8217;operazione di mostrare un fumetto contenente una stringa html (tramite il comando <code>openInfoWindowHtml</code>).</p>
<p>Come ultimo passaggio preparatorio dobbiamo istanziare l&#8217;oggetto <em>GDirections</em> di Google, che ci servirà per calcolare le rotte:</p>
<pre>
//Create directions module:
directions = new GDirections(map, directionsPanel);
</pre>
<p>Ora che tutto è pronto dobbiamo preoccuparci di cosa fare quando l&#8217;utente premerà sul pulsante &#8220;Calcola&#8221;:</p>
<pre>
submitButton.onclick = function() {
    getRoute();
    return false;
}
</pre>
<p>Definiamo quindi la funzione <code>getRoute()</code>:</p>
<pre>
function getRoute() {
	var userLocation = document.findRoute.partenza.value;
	from = userLocation;
	to  = home;

    directions.load("from: " + from + " to: " + to, {"locale":"it_IT"});
}
</pre>
<p>
Questa non fa altro che leggere la posizione di partenza dal campo compilato dall&#8217;utente e assegnarla alla variabile <em>from</em> e associare il punto base alla variabile <em>to</em>.<br />
La magia avviene infine nell&#8217;ultima riga, dove andremo a calcolare la rotta tramite il metodo load del nostro oggetto <em>GDirections</em>.
</p>
<p>
A questo andremo a passare due parametri: Il primo sarà una stringa contenente le indicazioni nella forma &#8220;from:INDIRIZZO_DI_PARTENZA to:INDIRIZZO_DI_ARRIVO&#8221; (esattamente a come faremmo nella casella di ricerca in maps.google.it). Il secondo parametro invece è un oggetto che ci permette di specificare varie opzioni, in questo caso la lingua italiana.
</p>
<p>
Se andiamo a testare il tutto, dovremmo vedere che, una volta scelto un indirizzo di partenza, automaticamente verrà generato un percorso, visualizzato correttamente nella mappa, e generato il percorso passo-passo con tutte le indicazioni. Semplice no?
</p>
<p><a href="http://www.cescopag.com/demos/directions/demo1.html" class="linkdemo" target="_blank">Demo 1</a></p>
<p>Ora aggiungiamo qualche funzionalità in più. Per prima cosa vogliamo dare la possibiltà di calcolare anche il percorso di ritorno. Aggiungiamo quindi un <em>checkbox</em> con la dicitura &#8220;Calcola percorso di ritorno&#8221;:</p>
<pre>
&lt;h1&gt;Come arrivare&lt;/h1&gt;
&lt;form name="findRoute" action=""&gt;
	&lt;p&gt;
		&lt;label for="partenza"&gt;Da dove parti?&lt;/label&gt;
		&lt;input type="text" name="partenza" /&gt;
	&lt;/p&gt;

	&lt;p&gt;
		&lt;label&gt;&lt;input type="checkbox" name="inverti" value="inverti" /&gt;Calcola percorso di ritorno&lt;/label&gt;
	&lt;/p&gt;

	&lt;p&gt;
		&lt;input type="submit" value="Calcola" name="calcola" id="calcola" /&gt;
	&lt;/p&gt;
&lt;/form&gt;
</pre>
<p>Nel javascript, all&#8217;interno di <em>getRoute</em>, andiamo quindi a gestire il caso in cui si voglia invertire la direzione:</p>
<pre>
function getRoute() {
	var userLocation = document.findRoute.partenza.value;
	var reverse = document.findRoute.inverti.checked;

	if (!reverse) {
		//andata...
		from = userLocation;
		to  = home;
	} else {
		//ritorno...
		from = home;
		to = userLocation;
	}

    directions.load("from: " + from + " to: " + to, {"locale":"it_IT"});
}
</pre>
<p>Viene infatti controllato se la <em>checkbox</em> è selezionata oppure no, e in caso positivo vengono invertite le posizioni di partenza e arrivo.</p>
<p>Se visualizziamo l&#8217;esempio vediamo quindi che selezionando il <em>checkbox</em> le indicazioni saranno invertite, partendo dal punto base fino alla destinazione inserita dall&#8217;utente.</p>
<p><a href="http://www.cescopag.com/demos/directions/demo2.html" class="linkdemo" target="_blank">Demo 2</a></p>
<p> Come ultima personalizzazione andiamo a sostituire l&#8217;icona di default con una scelta ad-hoc. Per farlo ci avvaleremo dell&#8217;ottimo sito: <a href="http://www.powerhut.co.uk/googlemaps/custom_markers.php">http://www.powerhut.co.uk/googlemaps/custom_markers.php</a> Il quale ci permette di caricare immagini in <em>gif</em>, <em>jpeg</em> e <em>png</em> per generare il corrispondente marcatore, completo di immagini e javascript.</p>
<p>  Nel mio caso il risultato fornito è il seguente: </p>
<pre>
var myIcon = new GIcon();
myIcon.image = 'markers/image.png';
myIcon.printImage = 'markers/printImage.gif';
myIcon.mozPrintImage = 'markers/mozPrintImage.gif';
myIcon.iconSize = new GSize(65,190);
myIcon.shadow = 'markers/shadow.png';
myIcon.transparent = 'markers/transparent.png';
myIcon.shadowSize = new GSize(160,190);
myIcon.printShadow = 'markers/printShadow.gif';
myIcon.iconAnchor = new GPoint(33,190);
myIcon.infoWindowAnchor = new GPoint(33,0);
myIcon.imageMap = [4...0]; //omesso per questioni di spazio
</pre>
<p>Per poter utilizzare l&#8217;icona dobbiamo modificare leggermente la riga dove viene creato il marker:</p>
<pre>
//Create marker:
marker = new GMarker(home, {icon:myIcon});
</pre>
<p>Abbiamo infatti aggiunto l&#8217;opzione <em>icon</em> che permette di specificare quale icona utilizzare.</p>
<p>
  Se visualizzamo quest&#8217;ultimo esempio vedremo una simpatica icona al posto del consueto pallino rosso.
</p>
<p><a href="http://www.cescopag.com/demos/directions/demo3.html" class="linkdemo" target="_blank">Demo 3</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2009/11/google-maps-api-calcola-il-percorso-nel-nostro-sito/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>jQuery zoom plugin</title>
		<link>http://www.cescopag.com/2009/01/jquery-zoom-plugin/</link>
		<comments>http://www.cescopag.com/2009/01/jquery-zoom-plugin/#comments</comments>
		<pubDate>Sun, 11 Jan 2009 14:24:06 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery ui]]></category>
		<category><![CDATA[zoom]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=87</guid>
		<description><![CDATA[Visitando il sito Apple Store è possibile vedere all&#8217;opera un interessante funzionalità che permette lo zoom delle foto direttamente nel loro spazio, senza aprire fastidiosi popup.
Grazie a jQuery e la sua estensione jQuery UI è possibile realizzare il medesimo effetto in maniera semplice. In particolare andremo ad utilizzare il plugin &#34;draggable&#34; di jQuery UI.
Demo

L&#8217;idea di [...]]]></description>
			<content:encoded><![CDATA[<p>Visitando il sito Apple Store è possibile vedere all&#8217;opera un interessante funzionalità che permette lo zoom delle foto direttamente nel loro spazio, senza aprire fastidiosi popup.</p>
<p>Grazie a jQuery e la sua estensione jQuery UI è possibile realizzare il medesimo effetto in maniera semplice. In particolare andremo ad utilizzare il plugin &quot;draggable&quot; di jQuery UI.</p>
<p style="text-align:center"><strong><a href="http://www.cescopag.com/demos/zoom/index.html">Demo</a></strong></p>
<p><span id="more-87"></span></p>
<p>L&#8217;idea di base è quella di prevedere un DIV contenente l&#8217;immagine a bassa risoluzione. Al click su questa immagine, questa viene ingrandita fino alle dimensioni dell&#8217;immagine a grande risoluzione e successivamente scambiata con quest&#8217;ultima in modo da simulare uno zoom. Tramite la funzionalità &quot;draggable&quot; renderemo trascinabile  questa immagine, in modo da poter visualizzare tutte le parti dell&#8217;ingrandimento. Il nostro riquadro originale che contiene la foto sarà la &quot;finestra&quot; attraverso cui si vedrà l&#8217;immagine ad alta risoluzione sottostante. Sarà inoltre necessario impostare posizionamenti e limiti di trascinamento per garantire che l&#8217;immagine non esca dal riquadro.<br />
  Ho realizzato una piccola animazione che rappresenta l&#8217;idea:</p>
<p style="text-align:center"><img src="http://www.cescopag.com/wp-content/uploads/2009/01/anim.gif" alt="Animazione Zoom" title="animazione zoom tool" width="300" height="200" class="size-full wp-image-88" /></p>
<p>Il riquadro rosso è l&#8217;area originale dell&#8217;immagine piccola (non rappresentata). L&#8217;immagine grande (la foto che vedete nell&#8217;animazione) potrà essere trascinata in tutte le direzioni e soltanto la parte all&#8217;interno del riquadro rosso sarà visibile, dando l&#8217;impressione di un&#8217;immagine zoomata su cui effettuiamo il panning. Il riquadro grigio invece rappresenta i limiti entro i quali l&#8217;immagine può essere trascinata senza uscire dal riquadro rosso. Vedremo dopo come realizzare tutto ciò.</p>
<p>Ma procediamo con ordine. Per prima cosa realizziamo l&#8217;html necessario. Come abbiamo detto realizziamo un DIV contenente l&#8217;immagine piccola. Per garantire l&#8217;accessibilità anche a chi non ha javascript abilitato, l&#8217;inseriamo all&#8217;interno di un link che punta all&#8217;immagine grande e che ci servirà per identificare il path all&#8217;immagine ad alta risoluzione:</p>
<pre>&lt;div class=&quot;image-zoom&quot;&gt;
&lt;a href=&quot;img1-big.jpg&quot;&gt;
&lt;img src=&quot;img1-small.jpg&quot; alt=&quot;img1&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;</pre>
<p>Ora che l&#8217;html è pronto possiamo procedere con gli opportuni stili css:</p>
<pre>.image-zoom { overflow:hidden; width:300px; height:300px; position:relative }
.image-zoom img { position:absolute; }</pre>
<p>Come potete vedere ho impostato l&#8217;overflow hidden per confinare l&#8217;immagine all&#8217;interno del riquadro quando viene zoomata (come se fosse una finestra) e le dimensioni coincidenti con la dimensione dell&#8217;immagine contenuta. Ho poi aggiunto il posizionamento relative al contenitore e absolute all&#8217;immagine, in modo da poterla muovere liberamente nel nostro div.</p>
<p>Ora che abbiamo tutto pronto possiamo procedere all&#8217;aggiunta del javascript necessario, il tutto grazie a jQuery e jQuery UI. Andiamo quindi a realizzare la struttura base per realizzare un plugin in jQuery:</p>
<pre>(function($){
$.fn.zoom = function(params) {
   var defaults = {
      duration: 200,
      small_width:300,
      small_height:300,
      big_width:1000,
      big_height:1000
   };
   var options = $.extend(defaults, params);
   return this.each(function() {
      //istruzioni del plugin...
   });
}
})(jQuery)</pre>
<p>La prima riga e l&#8217;ultima riga servono soltanto a garantirci di poter utilizzare la scorciatoia &quot;$&quot; al posto di &quot;jQuery&quot;, mentre tramite <code>$.fn.zoom = function(params) { ... }</code> andiamo a realizzare il plugin vero e proprio. La variabile <code>params</code> è l&#8217;insieme di opzioni che possiamo impostare all&#8217;inizializzazione del plugin, mentre <code>defaults</code> sono i valori di default che il plugin andrà ad utilizzare. Infine uniamo il tutto tramite il metodo <code>$.extend</code> nell&#8217;oggetto <code>options</code>, il quale che conterrà i valori di default eventualmente sovrascritti dai parametri passati in <code>params</code>. I parametri di default sono in particolare la durata delle animazioni di zoom-in e zoom-out e le dimensioni dell&#8217;immagine a bassa e alta risoluzione (per semplicità ipotizziamo di avere immagini di dimensioni fisse).<br />
Le istruzioni del plugin invece andranno inserite all&#8217;interno del ciclo <code>return this.each(function() {...});</code>. Tramite <code>each</code> infatti possiamo inizializzare la funzionalità del plugin a più elementi contemporaneamente.</p>
<p>Il motivo per cui ho deciso di realizzare un plugin anziché semplici istruzioni è che permette di avere un codice riutilizzabile facilmente, permette di scrivere codice molto più ordinato e di estenderne le funzionalità senza dover mettere mano a tutto il flusso di lavoro.</p>
<p>Ma vediamo in dettaglio come sarà strutturato il plugin. In generale prevediamo quattro parti: una prima parte dove andremo a preparare tutte le variabili che ci servono, una seconda parte dove manipolare css e html per preparare le funzionalità del plugin, una terza parte dove andremo a gestire gli eventi dell&#8217;utente, richiamando gli opportuni metodi, ed infine un&#8217;ultima parte dove andremo ad implementare le varie funzionalità (zoom in, zoom out, drag etc.).</p>
<h4>Prima parte</h4>
<pre>//caching...
var $container = $(this);
var $link = $container.find('a');
var $image = $link.find('img');

//reading some parameters...
var small_path = $image.attr('src');
var big_path   = $link.attr('href');

//status variables...
var dragging = false;
var zoomed   = false;

//calculate correct positioning...
var a_width  = (options.big_width  - options.small_width)  * 2 + options.small_width;
var a_height = (options.big_height - options.small_height) * 2 + options.small_height;

var a_top  = options.big_height - options.small_height;
var a_left = options.big_width  - options.small_width;</pre>
<p>La prima sezione serve per fare il &quot;caching&quot; degli elementi utilizzati in modo da semplificarne e velocizzarne l&#8217;utilizzo nel resto del plugin. Salviamo poi i path delle immagini a bassa e alta risoluzione che ci serviranno nelle operazioni di zoom-in e zoom-out. Le variabili <code>dragging</code> e <code>zoomed</code>, che impostiamo all&#8217;inizio a <code>false</code>, servono per salvare lo stato corrente delle immagini, in particolare se le stiamo trascinando e se sono zoomate o rimpicciolite. Nell&#8217;ultima sezione infine calcoliamo i posizionamenti e le larghezze che ci serviranno quando andremo a manipolare il css dell&#8217;html.</p>
<h4>Seconda parte</h4>
<pre>$link.css({
    display:'block',
    position:'absolute',
    width: a_width   + 'px',
    height: a_height + 'px',
    top:  '-' + a_top  + 'px',
    left: '-' + a_left + 'px'
});

/* Removing default link behaviour... */
$link.removeAttr('href');

$image.css({
    display:'block',
    position:'absolute',
    width:  options.small_width + 'px',
    height: options.small_height + 'px',
    top: a_top + 'px',
    left: a_left + 'px'
});</pre>
<p>Nella seconda parte andiamo a cambiare i css di link e immagine per predisporre la funzionalità di zoom. In particolare il link diventerà il blocco che conterrà lo spostamento dell&#8217;immagine grande (il rettangolo grigio nell&#8217;animazione). A questo andremo poi a togliere l&#8217;attributo <code>href</code>, in modo da eliminare il comportamento standard del link che interferirebbe con il nostro plugin. L&#8217;immagine infine viene riposizionata all&#8217;interno del tag <code>a</code> in modo da trovarsi in corrispondenza della finestra originale (il rettangolo rosso). Infatti mentre il link è spostato a sinistra e in alto tramite margini negativi, l&#8217;immagine viene spostata degli stessi valori (<code>a_top</code>, <code>a_left</code>) ma verso destra e in basso, in modo da trovarsi nel medesimo punto rispetto alla finestra originale. In questo modo avremo già pronti i posizionamenti assoluti per l&#8217;animazione.</p>
<h4>Terza parte</h4>
<pre>$image.mouseup(function() {
    if (!dragging) {
        if (zoomed) {
	        zoomOut();
        } else {
    	    zoomIn();
        }
    }
});</pre>
<p>L&#8217;unico evento che ci interessa gestire è il rilascio del pulsante del mouse. Utilizzando infatti l&#8217;evento &quot;mouseup&quot; anziché l&#8217;evento &quot;click&quot; possiamo controllare lo stato prima di decidere che operazione compiere. Al rilascio del mouse controllo se sto effettuando il &quot;dragging&quot;. Se non sto trascinando, e quindi è un semplice click, effettuo lo zoom-in o lo zoom-out in base allo stato &quot;zoomed&quot;, richiamando i due metodi <code>zoomOut()</code> e <code>zoomIn()</code>.</p>
<h4>Quarta parte</h4>
<p>Nella quarta parte andremo ad implementare i metodi zoomOut() e zoomIn() richiamati precedentemente, oltre a quelli che si renderanno necessari successivamente:</p>
<pre>function zoomOut() {
    $image.animate({
        width:options.small_width + 'px',
        height:options.small_height + 'px',
        top:  a_top  + 'px',
        left: a_left + 'px'
    }, options.duration, swapWithSmall);
	zoomed = false;
}

function zoomIn() {
    $image.animate({
        width:options.big_width + 'px',
        height:options.big_height + 'px',
        top:  a_top / 2  + 'px',
        left: a_left / 2 + 'px'
    }, options.duration, swapWithBig);
    zoomed = true;
}</pre>
<p></p>
<p>Come vedete ogni metodo va ad animare dimensioni e posizionamenti css secondo i valori calcolati nella prima parte. Alla fine dell&#8217;animazione vengono richiamati i due metodi per scambiare l&#8217;immagine, rispettivamente &quot;swapWithBig&quot; e swapWithSmall&quot;:</p>
<pre>function swapWithBig() {
	$image.attr('src', big_path);
	$image.draggable({
		containment: 'parent',
		start: handleStartDrag,
		stop: handleStopDrag
	});
}

function swapWithSmall() {
	$image.attr('src', small_path);
	$image.draggable('disable');
}

function handleStartDrag() {
	dragging = true;
}

function handleStopDrag() {
	dragging = false;
}</pre>
<p>Questi non fanno altro che cambiare l&#8217;attributo <code>src</code> e ad abilitare (nel caso dello zoom-in) o disabilitare (nel caso dello zoom-out) la funzionalità &quot;draggable&quot; di jQuery UI. Come vedete a draggable vengono impostati alcuni parametri:</p>
<p>containment: serve ad impostare i limiti di trascinamento. Nel nostro caso è impostato a <code>parent</code>, e cioè al tag html che contiene l&#8217;elemento e quindi il tag <code>a</code>  che abbiamo appositamente posizionato e dimensionato proprio per questo scopo.<br />
  start: è la funzione che viene eseguita quando inizia il trascinamento. Nel nostro caso è la funzione <code>handleStartDrag</code> che non fa altro che aggiornare la variabile di stato corrispondente (dragging).<br />
  stop: è la funzione che viene eseguita alla fine del trascinamento e richiama la funzione <code>handleStopDrag</code>, che aggiorna la variabile <code>dragging</code>.</p>
<p>Il plugin ora è completo, non ci resta che richiamarlo nella nostra pagina tramite la sintassi solita di jQuery:</p>
<pre>$(document).ready(function() {
	$('.image-zoom').zoom();
});</pre>
<p>Alcuni metodi possono sembrare superflui, ma ho preferito spezzettare il plugin in più funzioni esplicite, ciascuna con funzionalità ben definite, piuttosto che annidare funzioni su funzioni come jQuery a volte induce a fare. Questo semplifica la lettura del codice e soprattutto le successive manipolazioni e revisioni.</p>
<p>Ecco il codice completo del plugin, mentre <a href="http://www.cescopag.com/demos/zoom/index.html">qui potete vederlo in azione</a>:</p>
<pre>(function($) {
$.fn.zoom = function(params) {
	/*
	Zoom jQuery Plugin
	Copyright: (C) 3009 - Francesco Paggin
	Parameters:
		(int) duration: the duration of the zooming animaton
		(int) small_width, small_height: the dimensions of the small thumbnails
		(int) big_width, big_height: the dimensions of the zoomed images
	*/
	var defaults = {
		duration: 200,
		small_width:300,
		small_height:300,
		big_width:1000,
		big_height:1000
	};
	var options = $.extend(defaults, params);

	return this.each(function() {
		//caching...
		var $container = $(this);
		var $link = $container.find('a');
		var $image = $link.find('img');

		//reading some parameters...
		var small_path = $image.attr('src');
		var big_path   = $link.attr('href');

		//status variables...
		var dragging = false;
		var zoomed   = false;

		//calculate correct positioning...
		var a_width  = (options.big_width  - options.small_width)  * 2 + options.small_width;
		var a_height = (options.big_height - options.small_height) * 2 + options.small_height;

		var a_top  = options.big_height - options.small_height;
		var a_left = options.big_width  - options.small_width;

		/*
			INITIALIZATION...
		*/
		$link.css({
			display:'block',
			position:'absolute',
			width: a_width   + 'px',
			height: a_height + 'px',
			top:  '-' + a_top  + 'px',
			left: '-' + a_left + 'px'
		});

		/* Removing default link behaviour... */
		$link.removeAttr('href');

		$image.css({
			display:'block',
			position:'absolute',
			width:  options.small_width + 'px',
			height: options.small_height + 'px',
			top: a_top + 'px',
			left: a_left + 'px'
		});

		/*
			HANDLE EVENTS...
		*/
		$image.mouseup(function() {
			if (!dragging) {
				if (zoomed) {
					zoomOut();
				} else {
					zoomIn();
				}
			}
		});

		/*
			METHODS...
		*/
		function zoomOut() {
			$image.animate({
				width:options.small_width + 'px',
				height:options.small_height + 'px',
				top:  a_top  + 'px',
				left: a_left + 'px'
			}, options.duration, swapWithSmall);
			zoomed = false;
		}

		function zoomIn() {
			$image.animate({
				width:options.big_width + 'px',
				height:options.big_height + 'px',
				top:  a_top / 2  + 'px',
				left: a_left / 2 + 'px'
			}, options.duration, swapWithBig);
			zoomed = true;
		}

		function swapWithBig() {
			$image.attr('src', big_path);
			$image.draggable({
				containment: 'parent',
				start: handleStartDrag,
				stop: handleStopDrag
			});
		}

		function swapWithSmall() {
			$image.attr('src', small_path);
			$image.draggable('disable');
		}

		function handleStartDrag() {
			dragging = true;
		}

		function handleStopDrag() {
			dragging = false;
		}
	});
}
})(jQuery)</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2009/01/jquery-zoom-plugin/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Progetto Step by Step CodeIgniter &#8211; I Controller</title>
		<link>http://www.cescopag.com/2008/11/progetto-step-by-step-codeigniter-i-controller/</link>
		<comments>http://www.cescopag.com/2008/11/progetto-step-by-step-codeigniter-i-controller/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 22:30:34 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programmazione]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=78</guid>
		<description><![CDATA[In questo passaggio del tutorial a CodeIgniter vediamo finalmente l’elemento del framework che si occupa della logica dell’applicazione, e cioè il controller. Come vedremo questo elemento è quello che viene eseguito direttamente dall’utente ed è ciò che mette in comunicazione i dati (e cioè i modelli) con l’output (le viste).
CodeIgniter infatti, tramite la classe Routing, [...]]]></description>
			<content:encoded><![CDATA[<p>In questo passaggio del tutorial a CodeIgniter vediamo finalmente l’elemento del framework che si occupa della logica dell’applicazione, e cioè il controller. Come vedremo questo elemento è quello che viene eseguito direttamente dall’utente ed è ciò che mette in comunicazione i dati (e cioè i modelli) con l’output (le viste).</p>
<p>CodeIgniter infatti, tramite la classe Routing, si occupa di leggere l’URL digitato e indirizzare all’apposito controller il metodo da eseguire. Ad esempio, digitando l’indirizzo <code>http://www.dominio.com/index.php/nome_controller/nome_metodo/</code> CodeIgniter andrà a richiamare il controller <code>nome_controller</code> ed eseguirà il metodo <code>nome_metodo</code>. Se invece viene omesso <code>nome_metodo</code> verrà richiamato il metodo di default chiamato <code>index</code>.</p>
<p><span id="more-78"></span></p>
<p>Dal punto di vista del codice, un controller non è altro che una classe PHP che eredita dalla classe nativa <code>Controller</code>. Pertanto la sintassi base sarà:</p>
<pre>class Mia_classe extends Controller {
    function Mia_classe() { //questo è il costruttore
        parent::Controller(); //richiamo il costruttore della classe “Controller”
    }

    function index() {
        //funzione richiamata di default
    }

    function mia_funzione() {
        //metodo personalizzato
    }
}</pre>
<p>i controller vanno di norma salvati nella cartella <code>/system/application/controllers</code>, mentre il nome del file dovrà coincidere col nome della classe, quindi nell’esempio precedente questo dovrà chiamarsi <code>mia_classe.php</code> &#8211; Notare l’eliminazione delle maiuscole richiesta dal framework.</p>
<p>Tornando alla nostra applicazione, dato che abbiamo tre entità in gioco avremo bisogno di tre file separati. Ciò non è la regola, in quanto i controller vanno intesi più che altro come azioni da compiere. Nel nostro caso però, dato che andremo ad operare ogni volta su un elemento preciso in maniera abbastanza indipendente, ho preferito separarli in tre controller distinti anziché uno unico.</p>
<p>Partiamo dal controller delle tipologie (che sarà analogo a quello degli stati).</p>
<p>Prendendo come spunto il modello qui sopra, il nostro controller per gli stati sarà del tipo:</p>
<pre>class Statuses extends Controller {
    function Statuses() {
        parent::Controller();
        $this->load->model(‘status_model’);
    }

    function index() {
        //funzione richiamata di default
    }
}</pre>
<p>Come vedete nel costruttore <code>Statuses()</code> vado a caricare il modello <code>status_model</code> che mi servirà all’interno del controller.</p>
<p>Ora andiamo a popolare il <code>metodo index()</code> che ci servirà per la lista completa degli stati. Per farlo aggiungiamo: </p>
<pre>$data[‘statuses’] = $this->status_model->get();
$this->load->view(‘list_statuses’, $data);</pre>
<p>La prima riga si occupa di eseguire il metodo get del modello status_model e a salvarne l’output nell’array <code>$data</code>. Nella seconda riga invece andiamo a caricare la vista <code>list_statuses</code> passando i dati da visualizzare. CodeIgniter andrà a cercare la vista list_statuses.php all’interno della cartella <code>/system/application/views</code>. Vedremo in seguito come realizzare la vista, ma per quanto riguarda il Controller abbiamo già ottenuto quello che ci serve.</p>
<p>I prossimi metodi che ci servono sono quelli per interagire col sito. Infatti abbiamo previsto la possibilità di aggiungere, modificare o rimuovere stati direttamente dal sito senza dover accedere al database.</p>
<p>Presupponiamo già di avere un form che invii tramite post i campi necessari (andremo a realizzarlo in una delle viste). Il nostro metodo che chiameremo <code>add()</code> sarà:</p>
<pre>function add() {
    if ($this->input->post(‘submit’) {
        //ho fatto il submit...
        $insert[‘name’] = $this->input->post(‘name’);
        $this->status_model->add($insert);
        return $this->index();
    } else {
        //non ho fatto il submit quindi mostro il form...
        $this->load->view(‘add_status’);
    }
}</pre>
<p>Innanzitutto vedo se ho già fatto il submit o se invece devo mostrare il form per l’inserimento. Nel primo caso leggo i dati tramite <code>$this->input->post('nome')</code> che è il metodo offerto dalla libreria <em>Input</em> di C.I. per leggere i dati in POST, richiamo il metodo <code>add()</code> del modello per seguire l’inserimento. Una volta concluso mostro la lista degli articoli richiamando il metodo di default <code>$this->index()</code></p>
<p>La funzione <code>edit()</code> è molto simile, con la differenza che dovendo modificare un preciso stato dovrò specificarlo tramite id. Per farlo basta passare quest&#8217;ultimo come parametro al nostro metodo. Nel browser ciò è possibile nella forma: <code>http://www.dominio.com/index.php/mio_controller/metodo/parametro1/parametro2/</code> etc&#8230;</p>
<p>Il metodo diventa quindi:</p>
<pre>function edit($id) {
    if ($this->input->post(‘submit’) {
        //ho fatto il submit...
        $insert[‘name’] = $this->input->post(‘name’);
        $this->status_model->edit($insert, $id);
        return $this->index();
    } else {
        //non ho fatto il submit quindi mostro il form...
        $data[‘status’] = $this->status_model->get_single($id);
        $this->load->view(‘add_status’, $data);
    }
}</pre>
<p>Come vedete l’unica differenza rispetto all’inserimento sta che nel metodo <code>edit()</code> del modello devo passare anche l’id dell’elemento da modificare. Devo inoltre pre-popolare il form con i valori già esistenti. Posso farlo tramite il metodo <code>get_single($id)</code> del nostro modello, che ci permette di leggere un singolo stato e passarne i dati alla vista.</p>
<p>L’ultimo metodo è quello destinato alla cancellazione di uno stato, ed è molto semplice:</p>
<pre>function delete($id) {
    $this->status_model->delete($id);
    return $this->index();
}</pre>
<p>Come avrete sicuramente visto non viene effettuato nessun controllo sulla validità dei dati. Questo però sarà facilmente integrabile in un secondo momento tramite ulteriori controlli e la libreria <em>Validation</em> presente in CodeIgniter.</p>
<p>Il controller <code>Types</code> sarà identico a quanto appena visto, con l’unica differenza di nomenclatura tra stati e tipi. Basterà quindi fare copia-incolla dei files e modificare quanto serve.</p>
<p>Anche il controller relativo agli items sarà molto simile, con la differenza che avremo più campi da gestire (non solo il nome) e avremo bisogno di tutti e tre i modelli. Il controller completo è il seguente:</p>
<pre>class Items extends Controller {

    function Items() {
        parent::Controller();
        $this->load->model('item_model');
        $this->load->model('type_model');
        $this->load->model('status_model');
    }

    function index() {
        //lista degli elementi nel database
        $data['items'] = $this->item_model->get();
        $this->load->view('list_items', $data);
    }

    function add() {
        if ($this->input->post('submit')) {
            $insert['name']             = $this->input->post('name');
            $insert['code']             = $this->input->post('code');
            $insert['description']      = $this->input->post('description');
            $insert['position']         = $this->input->post('position');
            $insert['type_id']          = $this->input->post('type_id');
            $insert['status_id']        = $this->input->post('status_id');
            $insert['about_the_status'] = $this->input->post('about_the_status');

            $this->item_model->add($insert);
            return $this->index(); //torno all'indice...
        } else {
            $data['types']    = $this->type_model->get();
            $data['statuses'] = $this->status_model->get();
            $this->load->view('add_item', $data);
        }
    }

    function edit($id) {
        if ($this->input->post('submit')) {
            $insert['name']             = $this->input->post('name');
            $insert['code']             = $this->input->post('code');
            $insert['description']      = $this->input->post('description');
            $insert['position']         = $this->input->post('position');
            $insert['type_id']          = $this->input->post('type_id');
            $insert['status_id']        = $this->input->post('status_id');
            $insert['about_the_status'] = $this->input->post('about_the_status');

            $this->item_model->edit($insert, $id);
            return $this->index(); //torno all'indice...
        } else {
            $data['item']     = $this->item_model->get_single($id);
            $data['types']    = $this->type_model->get();
            $data['statuses'] = $this->status_model->get();
            $this->load->view('edit_item', $data);
        }
    }

    function delete($id) {
        $this->item_model->delete($id);
        return $this->index();
    }
}</pre>
<p>Anche se più lungo, il concetto è il medesimo dei precedenti. Vorrei soffermarmi semplicemente sulle istruzioni</p>
<pre>$data[‘types’] = $this->type_model->get();
$data[‘statuses’] = $this->status_model->get();</pre>
<p>presenti sia nel metodo per l’inserimento che per quello per la cancellazione. In pratica andiamo a prepararci in due array l’elenco degli stati e delle tipologie disponibili nel nostro database. Questo ci serve per realizzare delle comode dropdown nei form per i riferimenti esterni. Quando vedremo in dettaglio le viste capiremo meglio come andremo a utilizzarlo.</p>
<p>Nella prossima puntata vedremo in dettaglio le viste, completando il primo step e potendo far funzionare una prima basilare applicazione. In seguito, come già accennato, vedremo come gestire la validazione dei dati.</p>
<p>Puntate precedenti:</p>
<ol>
<li><a href="http://www.cescopag.com/2008/08/progetto-step-by-step-codeigniter-introduzione/">Introduzione</a></li>
<li><a href="http://www.cescopag.com/2008/08/progetto-step-by-step-codeigniter-il-database/">Il database</a></li>
<li><a href="http://www.cescopag.com/2008/08/progetto-step-by-step-codeigniter-i-modelli/">I modelli</a></li>
<li><a href="http://www.cescopag.com/2008/10/progetto-step-by-step-codeigniter-lapplicazione/">L&#8217;applicazione</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/11/progetto-step-by-step-codeigniter-i-controller/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Footer sempre in fondo</title>
		<link>http://www.cescopag.com/2008/11/footer-sempre-in-fondo/</link>
		<comments>http://www.cescopag.com/2008/11/footer-sempre-in-fondo/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 20:56:59 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[footer]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[trick]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/2008/11/footer-sempre-in-fondo/</guid>
		<description><![CDATA[Il footer, per definizione, è quell&#8217;elemento che chiude la pagina e si pone alla fine dei contenuti. Quando però il contenuto è più corto dello spazio disponibile  a video &#8211; il viewport &#8211; il footer si &#8220;solleva&#8221; dal bordo inferiore della pagina, lasciando uno spazio più o meno grande al di sotto di esso. [...]]]></description>
			<content:encoded><![CDATA[<p>Il footer, per definizione, è quell&#8217;elemento che chiude la pagina e si pone alla fine dei contenuti. Quando però il contenuto è più corto dello spazio disponibile  a video &#8211; il <em>viewport</em> &#8211; il footer si &#8220;solleva&#8221; dal bordo inferiore della pagina, lasciando uno spazio più o meno grande al di sotto di esso. L&#8217;effetto in certi casi può essere poco gradevole, dando l&#8217;impressione di un layout &#8220;tagliato a metà&#8221;. Potete vedere <a href="http://www.cescopag.com/demos/footer/inizio.html">qui un esempio</a>&#8230;<br />
<span id="more-68"></span><br />
Il footer dovrebbe invece disporsi allineato al bordo inferiore della pagina nel caso citato, mentre dovrebbe posizionarsi in fondo al contenuto, oltre lo scroll, se questo è sufficientemente lungo da riempire tutto il viewport. Per farvi un&#8217;idea date un&#8217;occhiata <a href="http://www.cescopag.com/demos/footer/fine.html" target="_blank">qui</a> e <a href="http://www.cescopag.com/demos/footer/fine_lungo.html" target="_blank">qui</a>.</p>
<p>Una soluzione valida, compatibile con tutti i moderni browser, è quella di utilizzare la proprietà css <span style="font-style: italic;">min-height</span> per imporre l&#8217;altezza minima del contenuto tale da farlo ampliare fino a riempire con il viewport. </p>
<p>Ma procediamo con ordine. Il layout standard potrebbe essere questo:</p>
<pre>&lt;body&gt;
&nbsp;&nbsp;&nbsp; &lt;div id="<span style="font-weight: bold;">container</span>"&gt;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &lt;div id="header"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Header
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &lt;/div&gt;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp; &lt;div id="content"&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Content
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;  &nbsp;&nbsp;  &lt;/div&gt;
&nbsp;&nbsp;&nbsp; &lt;/div&gt;
&nbsp;&nbsp;&nbsp; &lt;div id="<span style="font-weight: bold;">footer</span>"&gt;
        Footer
&nbsp;&nbsp;&nbsp; &lt;/div&gt;
&lt;/body&gt;
</pre>
<p>Tramite css impostiamo l&#8217;altezza minima del <span style="font-style: italic;">container</span> al 100% in modo da farlo occupare tutto lo spazio verticale disponibile. L&#8217;altezza viene però calcolata in base a quella degli elementi contenenti il div, quindi dobbiamo impostare al 100% sia il tag <span style="font-style: italic;">body</span> che il tag <span style="font-style: italic;">html</span>:</p>
<pre>html, body {
&nbsp;&nbsp;&nbsp; height:100%;
}

#container {
&nbsp;&nbsp;&nbsp; min-height:100%;
}</pre>
<p>In questo modo però il footer andrà a posizionarsi fuori dall&#8217;area visibile (oltre il 100%, per intendersi): occorre quindi recuperare lo spazio necessario. Per farlo utilizziamo un semplice margine negativo pari all&#8217;altezza voluta del footer (in pixel o em, come preferite): </p>
<pre>html, body {
&nbsp;&nbsp;&nbsp; height:100%;
}

#container {
&nbsp;&nbsp;&nbsp; min-height:100%;
    <span style="font-weight: bold;">margin-bottom:-100px;</span>
}</pre>
<p>Ora però dobbiamo impedire al contenuto di finire sotto al footer che abbiamo portato in primo piano. Aggiungiamo perciò un padding inferiore al content in modo da distanziarlo a sufficienza: è importante quindi che abbia almeno lo stesso valore. Se vogliamo aggiungere un ulteriore spazio basta addizionarlo: (ad es. 110px per un padding inferiore apparente di 10px).</p>
<pre>html, body {
&nbsp;&nbsp;&nbsp; height:100%;
}

#container {
&nbsp;&nbsp;&nbsp; min-height:100%;
    margin-bottom:-<span style="font-weight: bold;">100px</span>;
}

#content {
    <span style="font-weight: bold;">padding-bottom:100px</span>;
}
</pre>
<p>Se provate la pagina con un browser come Firefox o Safari noterete che abbiamo già ottenuto l&#8217;effetto desiderato. La proprietà <span style="font-style: italic;">min-height</span> però non è supportata da Internet Explorer 6. Possiamo risolvere facilmente con il noto l&#8217;hack che utilizza la proprietà <span style="font-style: italic;">!important</span>. Aggiorniamo quindi il css ed abbiamo finito:</p>
<pre>#body {
&nbsp;&nbsp;&nbsp; height:100%;
}

#container {
&nbsp;&nbsp;&nbsp; min-height:100%;<br style="font-weight: bold;" /><span style="font-weight: bold;">    height:auto !important;</span> /*per gli altri browser*/<br style="font-weight: bold;" /><span style="font-weight: bold;">    height:100%;</span> /*per IE 6*/
    margin-bottom:-100px;
}

#content {
    padding-bottom:100px;
}</pre>
<p>Ecco quindi <a href="http://www.cescopag.com/demos/footer/fine.html">l&#8217;esempio finito</a> con <a href="http://www.cescopag.com/demos/footer/fine.html">poco</a> o <a href="http://www.cescopag.com/demos/footer/fine_lungo.html">molto contenuto</a>. Potete in alternativa <a href="http://www.cescopag.com/demos/footer/footer.zip">scaricare lo zip</a> con i sorgenti.<br />
Ho aggiunto qualche altra istruzione per evidenziare header e footer, ma il css di base è lo stesso.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/11/footer-sempre-in-fondo/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Progetto Step by Step Codeigniter &#8211; l&#8217;applicazione (edit)</title>
		<link>http://www.cescopag.com/2008/10/progetto-step-by-step-codeigniter-lapplicazione/</link>
		<comments>http://www.cescopag.com/2008/10/progetto-step-by-step-codeigniter-lapplicazione/#comments</comments>
		<pubDate>Thu, 09 Oct 2008 12:46:43 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Coding]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=43</guid>
		<description><![CDATA[Riprendo dopo qualche tempo il tutorial su CodeIgniter, dato che ho ultimato una prima versione preliminare dell&#8217;applicazione (molto scarna, ma rende l&#8217;idea). Potete quindi già testarne il funzionamento e seguire i prossimi tutorial direttamente sul codice finito.
L&#8217;installazione è semplicissima se avete un webserver php attivo con mysql configurato. Provate visitando l&#8217;indirizzo http://localhost/ (altrimenti esistono ambienti [...]]]></description>
			<content:encoded><![CDATA[<p>Riprendo dopo qualche tempo il tutorial su CodeIgniter, dato che ho ultimato una prima versione preliminare dell&#8217;applicazione (molto scarna, ma rende l&#8217;idea). Potete quindi già testarne il funzionamento e seguire i prossimi tutorial direttamente sul codice finito.</p>
<p>L&#8217;installazione è semplicissima se avete un webserver php attivo con mysql configurato. Provate visitando l&#8217;indirizzo <a href="http://localhost/">http://localhost/</a> (altrimenti esistono ambienti preconfigurati come <a href="http://www.apachefriends.org/en/xampp-windows.html">XAMPP</a> per windows o <a href="http://www.mamp.info/en/index.php">MAMP</a> per macintosh molto facili da installare).</p>
<p>Innanzitutto scaricate il file contenente tutto il necessario: <a href='http://www.cescopag.com/wp-content/uploads/2008/10/archivio.zip'>[Scarica]</a></p>
<p>Create poi una cartella (io l&#8217;ho chiamata &#8220;homeDB&#8221;) all&#8217;interno del vostro &#8220;localhost&#8221; (dove avete le cartelle dei vostri progetti in php, per intenderci) e scompattate all&#8217;interno il file zip. Quest&#8217;ultimo contiene, oltre al framework e all&#8217;applicazione, un file SQL per creare le tabelle necessarie (eseguite la query all&#8217;interno di phpMyAdmin o della vostra interfaccia MySQL preferita).</p>
<p>Ora non resta che modificare la configurazione dell&#8217;applicazione per adattarla al vostro ambiente. Per prima cosa aprite il file <code>config.php</code> all&#8217;interno di <code>[vostraCartella]/system/application/config/</code> e modificate la riga <code>$config['base_url'] = "http://127.0.0.1/homeDB/";</code> con la vostra cartella al posto di <em>homeDB</em>.</p>
<p>In secondo luogo bisognerà indicare i nuovi parametri di connessione al database. Per farlo aprite <code>database.php</code> nella stessa cartella e modificate in fondo alla pagina i parametri con quelli corretti.</p>
<p>A questo punto tutto dovrebbe essere configurato correttamente e dovreste già poter vedere l&#8217;applicazione funzionante visitando l&#8217;indirizzo <code>http://localhost/[vostraCartella]</code>. Potete creare qualche record fittizio per provare il tutto: vi suggerisco di partire dalle tipologie e dagli stati dato che sono campi obbligatori. Potete anche vedere, nell&#8217;inserimento degli articoli, la libreria <em>Validation</em> fornita direttamente da CodeIgniter (provate a creare un articolo vuoto).</p>
<p>Nei prossimi giorni vedremo gli altri elementi dell&#8217;applicazione, ovvero i controller e le viste, nonché l&#8217;utilizzo di helper e librerie.</p>
<h4>Edit: ho messo on-line una demo di questo primo abbozzo di applicazione a <a href="http://www.cescopag.com/demos/homeDB/">questo indirizzo</a> se volete provarla &#8220;dal vivo&#8221;. Mi raccomando non scrivete oscenità <img src='http://www.cescopag.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </h4>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/10/progetto-step-by-step-codeigniter-lapplicazione/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>jQuery plugin</title>
		<link>http://www.cescopag.com/2008/09/jquery-plugin/</link>
		<comments>http://www.cescopag.com/2008/09/jquery-plugin/#comments</comments>
		<pubDate>Tue, 23 Sep 2008 20:33:38 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=38</guid>
		<description><![CDATA[Oggi ho realizzato un piccolo plugin in jQuery che ben si presta a fare da breve introduzione allo sviluppo di plugin per il famoso framework javascript.
Quello di cui avevo bisogno era un plugin per simulare il comportamento della pseudo-classe &#8220;focus&#8221; in modo da renderla compatibile con tutti i browser. Nella fattispecie quando ci si posiziona [...]]]></description>
			<content:encoded><![CDATA[<p>Oggi ho realizzato un piccolo plugin in jQuery che ben si presta a fare da breve introduzione allo sviluppo di plugin per il famoso framework javascript.</p>
<p>Quello di cui avevo bisogno era un plugin per simulare il comportamento della pseudo-classe <em>&#8220;focus&#8221;</em> in modo da renderla compatibile con tutti i browser. Nella fattispecie quando ci si posiziona su un campo di input, a questo viene aggiunta una classe in modo da cambiarne lo stile. In questo modo si evidenzia all&#8217;utente il campo in cui sta operando favorendo l&#8217;accessibilità e l&#8217;usabilità.</p>
<p><span id="more-38"></span></p>
<p>Ma veniamo al sodo. Il comando base che useremo per estendere jQuery è il metodo <code>$.fn.nomePlugin = function() {}</code>. Possiamo passare alla funzione i parametri per la configurazione, nel caso il nostro plugin ne abbia bisogno. La prassi è di utilizzare come parametro un singolo oggetto contenente i vari parametri, in modo da rendere il codice più leggibile ed espandibile. Nel nostro caso è sufficiente un unico parametro che sarà il nome della classe che verrà aggiunta agli elementi durante il focus. Cominciamo quindi a scrivere:</p>
<pre>$.fn.pseudoFocus = function(params) {
    defaults = {classe: 'hasFocus'};
    options = $.extend(defaults, params);
}</pre>
<p>Come vedete utilizzo il parametro <code>params</code> per i valori passati dall&#8217;utente e <code>defaults</code> per le impostazioni di default appunto. Tramite il comando <code>$.extend(defaults, params)</code> jQuery &#8220;estende&#8221; i valori di default con i nuovi valori passati al plugin. In pratica vengono modificati solo i parametri diversi da quelli di default, lasciando gli altri inalterati.</p>
<p>Ora che abbiamo tutte le informazioni passiamo alla funzionalità vera e propria del plugin:</p>
<pre>$.fn.pseudoFocus = function(params) {
	//valori di default
    defaults = {classe: 'hasFocus'};
    options = $.extend(defaults, params);

    return this.each(function() {
    	var element = $(this); //opero sull'elemento che qui è individuato da "this"
    	//qui va il nostro codice...
    });

}</pre>
<p>Come evidenziato da <code>return this.each(function() {...})</code> il corpo del plugin deve ritornare un ciclo. Questo perché jQuery opera su tutti gli elementi individuati dal selettore usato, quindi nel caso in cui ce ne siano più d&#8217;uno dovremo eseguire il plugin su ciascuno di essi. All&#8217;interno del nostro ciclo quindi il singolo elemento sarà individuato da <code>$(this)</code>. Per comodità assegnamo l&#8217;elemento ad una variabile che ho chiamato <code>element</code>.</p>
<p>Il nostro plugin, come accennato prima, deve aggiungere agli elementi la classe desiderata durante l&#8217;evento <em>focus</em> e rimuoverla durante l&#8217;evento <em>blur</em>. Aggiungiamo quindi questi metodi:</p>
<pre>$.fn.pseudoFocus = function(params) {
	//valori di default
    defaults = {classe: 'hasFocus'};
    options = $.extend(defaults, params);

    return this.each(function() {
    	var element = $(this); //opero sull'elemento che qui è individuato da "this"
    	//qui va il nostro codice...
    	element.focus(function() {
    		element.addClass(options.classe);
    	});
    	element.blur(function() {
    		element.removeClass(options.classe);
    	});
    });
}</pre>
<p>Come vedete all&#8217;interno dei due metodi appena citati viene aggiunta o tolta la classe grazie a <code>element.addClass(options.classe)</code> e <code>element.removeClass(options.classe)</code>, i metodi di jQuery per manipolare le classi. Come vedete ho utilizzato il nostro oggetto <code>options</code> che contiene la classe desiderata (sia essa quella di default o quella fornita in fase di inizializzazione del plugin).</p>
<p>Ci rimane però un ultimo step. Come vedete abbiamo sempre utilizzato l&#8217;abbreviazione <strong>$</strong> al posto di <strong>jQuery</strong>. Questo potrebbe generare conflitti con altre librerie che utilizzano lo stesso metodo (prototype e motools, tanto per citarne due&#8230;). Per fortuna possiamo sfruttare la sintassi di javascript per aggiungere una &#8220;schermatura&#8221; (in inglese &#8220;closure&#8221;) in modo da poter utilizzare liberamente il dollaro all&#8217;interno del plugin senza però interferire con ciò che viene usato all&#8217;esterno. Per farlo basta utilizzare la forma (function($) {&#8230;})(jQuery). Questa non fa altro che definire la funzione anonima <code>function($) {...}</code> ed utilizzarla subito passando come parametro <code>jQuery</code>. In questo modo <strong>$</strong> diventa una variabile interna alla funzione e quindi il nostro plugin può utilizzarla liberamente.</p>
<p>Il plugin finito è quindi:</p>
<pre>(function($) {
    $.fn.pseudoFocus = function(params) {
	    //valori di default
        defaults = {classe: 'hasFocus'};
        options = $.extend(defaults, params);

        return this.each(function() {
    	    var element = $(this); //opero sull'elemento che qui è individuato da "this"
            //qui va il nostro codice...
            element.focus(function() {
                element.addClass(options.classe);
            });
            element.blur(function() {
                element.removeClass(options.classe);
            });
        });
    }
})(jQuery)</pre>
<p>Salviamo il file come <strong>jquery.pseudoFocus.js</strong> nella stessa cartella di jQuery. Per utilizzarlo dobbiamo richiamarlo nella pagina subito dopo il tag &#8220;script&#8221; che richiama jQuery. Dovremo poi eseguirlo dopo il caricamento del DOM tramite la sintassi <code>$(document).ready(...)</code>:</p>
<pre>&lt;script type="text/javascript" src="jquery.js"></script>
&lt;script type="text/javascript" src="jquery.pseudoFocus.js"></script>

$(document).ready(function() {
    $('input[type=text], input[type=password], textarea').pseudoFocus({classe: 'miaClasse'});
});</pre>
<p>Come vedete vengono prelevati gli input di tipo text, password e le textarea (ma avrei potuto utilizzare un qualsiasi elemento) e viene loro assegnato l&#8217;effetto focus tramite la classe &#8220;miaClasse&#8221;. Basterà realizzare un css adeguato e il gioco sarà fatto.</p>
<p>Come considerazione finale c&#8217;è da dire che la pseudo-classe focus è supportata da molti browser moderni e quindi l&#8217;esecuzione del plugin non è sempre necessaria. Ci basterebbe infatti utilizzare &#8220;:focus&#8221; nel css al posto di .miaClasse ed avremmo il medesimo effetto.
<p>Non ho voluto dilungarmi su questo ma focalizzarmi su come stendere un semplice plugin. Nell&#8217;utilizzo reale avremmo potuto controllare la versione del browser tramite <code>$.browser</code> e decidere di conseguenza se applicare o meno la classe.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/09/jquery-plugin/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>XML Cross-domain con PHP</title>
		<link>http://www.cescopag.com/2008/09/xml-cross-domain-con-php/</link>
		<comments>http://www.cescopag.com/2008/09/xml-cross-domain-con-php/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 22:51:41 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=32</guid>
		<description><![CDATA[Come potete vedere qui a destra ho implementato da poco le API di last.fm tramite i feed xml.
Nel mio post precedente ho spiegato come utilizzare i dati in Xml nel codice PHP per creare i propri widget. Questo sistema però ha un inconveniente: finché il php non ha avuto il file dal server di last.fm [...]]]></description>
			<content:encoded><![CDATA[<p>Come potete vedere qui a destra ho implementato da poco le API di last.fm tramite i feed xml.</p>
<p>Nel mio post precedente ho spiegato come utilizzare i dati in Xml nel codice PHP per creare i propri widget. Questo sistema però ha un inconveniente: finché il php non ha avuto il file dal server di last.fm la pagina non viene completata e il sito non si carica. E questo vale in generale.</p>
<p>Tramite javascript invece i contenuti vengono aggiunti dopo e se per qualche motivo il server non rispondesse, avremmo comunque possibilità di consultare il sito. E&#8217; per questo che ho deciso di implementare la soluzione via jQuery.</p>
<p><span id="more-32"></span></p>
<p>Il problema è che per questioni di sicurezza non è consentito eseguire richieste ajax tra domini diversi (come in questo caso) a meno che non si utilizzi l&#8217;apposito formato JSON (come ho fatto con le API flickr, sempre qui a fianco) &#8211; che però last.fm non mette a disposizione gratuitamente.</p>
<p>Ho risolto il problema con un trucchetto creando una paginetta in php che si occupa di prelevare l&#8217;xml da last.fm e stamparlo così com&#8217;è. Il vantaggio è che tramite jQuery devo fare una semplice chiamata ad un file locale, del tipo &#8220;ajax.php?url=&#8230;&#8221; evitando quindi il problema del cross-domain ed evitando di fare il parsing direttamente nella pagina principale, col rischio di bloccarla in attesa di last.fm.</p>
<p>Il codice che ho usato è questo:</p>
<pre>&lt;?php
if (isset($_GET['url'])) {
    $url = $_GET['url'];
    echo(@file_get_contents($url));
}
?&gt;</pre>
<p>Mentre nella chiamata ajax utilizzo l&#8217;url:</p>
<pre>/ajax.php?url=ws.audioscrobbler.com/1.0/user/cescopag/topalbums.xml</pre>
<p>che risulta quindi un path locale.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/09/xml-cross-domain-con-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google Static Maps</title>
		<link>http://www.cescopag.com/2008/09/google-static-maps/</link>
		<comments>http://www.cescopag.com/2008/09/google-static-maps/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 19:12:30 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=27</guid>
		<description><![CDATA[
Molti di voi probabilmente conoscono il servizio Google Maps, l&#8217;avrete visto sicuramente in molti siti. Nella stragrande maggioranza viene usato via javascript tramite le API pubbliche o tramite iFrame.
Qualche volta però queste soluzioni non sono applicabili, ad esempio se stiamo realizzando un sito per dispositivi portatili che non supportano bene i contenuti dinamici, oppure se [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.cescopag.com/wp-content/uploads/2008/09/staticmap.gif" alt="staticmap.gif" border="0" width="200" height="200" align="right" />
<p>Molti di voi probabilmente conoscono il servizio <strong><a href="http://maps.google.com" target="_blank">Google Maps</a></strong>, l&#8217;avrete visto sicuramente in molti siti. Nella stragrande maggioranza viene usato via javascript tramite le API pubbliche o tramite iFrame.</p>
<p>Qualche volta però queste soluzioni non sono applicabili, ad esempio se stiamo realizzando un sito per dispositivi portatili che non supportano bene i contenuti dinamici, oppure se non vogliamo appesantire la pagina con troppe mappe dinamiche, o in generale per tutte quelle situazioni dove javascript non è la soluzione migliore.</p>
<p>La cosa che forse non tutti sanno è che Google mette a disposizione anche la possibilità di generare <strong>mappe statiche</strong>, che diventano quindi <strong>semplici immagini jpeg, gif o bitmap</strong>. I vantaggi possono essere moltissimi:</p>
<p><span id="more-27"></span></p>
<ul>
<li><strong>La compatibilità</strong> (praticamente qualsiasi browser o dispositivo supporta le immagini, cosa che non si può dire di javascript)</li>
<li><strong>La velocità</strong> (anziché interrogare ogni volta i server Google per ottenere una mappa, possiamo pregenerare l&#8217;immagine, salvarla nel nostro server ed utilizzarla nelle pagine)</li>
<li><strong>La leggerezza</strong> (se dobbiamo inserire molte piccole mappe, per esempio per una serie di indirizzi, non dovremo appesantire la pagina con tutto il javascript necessario per ogni mappa)</li>
<li><strong>La flessibilità</strong> (il fatto di avere un&#8217;immagine &#8220;fisica&#8221; ci permette di processarla tramite le librerie fornite dai vari linguaggi, ad esempio per aggiungere bordi, effetti, sovraimpressioni etc.)</li>
</ul>
<p>Ma veniamo all&#8217;utilizzo. Innanzitutto è necessario procurarsi una chiave API per nostro sito (<a href="http://code.google.com/apis/maps/signup.html">http://code.google.com/apis/maps/signup.html</a>). Una volta ottenuta possiamo comporre un URL che contiene tutte le nostre specifiche della mappa richiesta. Google provvederà a restituirci un&#8217;immagine nel formato desiderato.</p>
<p>Per sapere come comporre l&#8217;URL vi basta visitare i link della documentazione:</p>
<ul>
<li><a href="http://code.google.com/apis/maps/documentation/staticmaps/">http://code.google.com/apis/maps/documentation/staticmaps/</a></li>
<li><a href="http://googlemapsapi.blogspot.com/2008/02/google-maps-without-scripting.html">http://googlemapsapi.blogspot.com/2008/02/google-maps-without-scripting.html</a></li>
<li><a href="http://gmaps-samples.googlecode.com/svn/trunk/simplewizard/makestaticmap.html">http://gmaps-samples.googlecode.com/svn/trunk/simplewizard/makestaticmap.html</a></li>
</ul>
<p>Vi anticipo che non sono supportate tutte le opzioni di Google Maps via Javascript, tuttavia è possibile indicare &#8211; oltre alla posizione e allo zoom &#8211; vari punti sulla mappa, personalizzarne gli indicatori (colore, dimensione e lettera), disegnare path, scegliere le dimensioni dell&#8217;immagine (fino ad un massimo di 640&#215;480 pixels) e il formato (jpeg, png, gif). Praticamente tutto quello che ci può servire!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/09/google-static-maps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flickr Feeds</title>
		<link>http://www.cescopag.com/2008/08/flickr-feeds/</link>
		<comments>http://www.cescopag.com/2008/08/flickr-feeds/#comments</comments>
		<pubDate>Sun, 31 Aug 2008 07:22:28 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[flickr]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=26</guid>
		<description><![CDATA[Continua la mia caccia alla ricerca di API e feed per i servizi di social network più diffusi. Stavolta tocca a Flickr.
Anche qui il nostro obiettivo è reperire le nostre ultime foto per utilizzarle nel proprio sito come più ci aggrada.
Pur non essendo disponibili liberamente tutte le API, per i nostri scopi possiamo utilizzare i [...]]]></description>
			<content:encoded><![CDATA[<p>Continua la mia caccia alla ricerca di API e feed per i servizi di social network più diffusi. Stavolta tocca a <a href="http://www.flickr.com/">Flickr</a>.</p>
<p>Anche qui il nostro obiettivo è reperire le nostre ultime foto per utilizzarle nel proprio sito come più ci aggrada.</p>
<p>Pur non essendo disponibili liberamente tutte le API, per i nostri scopi possiamo utilizzare i feeds pubblici forniti da Flickr.</p>
<p><span id="more-26"></span></p>
<p>L&#8217;indirizzo base da cui partire è il seguente: <code>http://api.flickr.com/services/feeds/photos_public.gne</code> a cui dovremo passare alcuni parametri.</p>
<p>Innanzitutto dobbiamo procurarci il nostro id. Per farlo basta andare nel proprio album e, in fondo alla pagina, trovare il link ai feed RSS. Troverete nell&#8217;indirizzo un parametro &#8220;id&#8221; che rappresenta appunto il vostro ID e che dovete segnarvi.</p>
<p>Una volta reperito l&#8217;id lo aggiungiamo all&#8217;indirizzo del nostro feed, che diventa quindi <code>http://api.flickr.com/services/feeds/photos_public.gne?id=88988666@N00</code> (ho usato il mio ID).</p>
<p>Infine possiamo specificare il formato preferito. A seconda delle nostre necessità possiamo optare per il formato RSS, Atom o l&#8217;utile JSON. Flickr inoltre ci mette a disposizione vari altri formati, ad esempio &mdash; cito &mdash; &#8220;php, php_serial, csv, json, sql, yaml, cdf e altri ancora&#8221;. Ipotizzando di voler manipolare i dati tramite javascript e quindi di richiedere il formato JSON l&#8217;url diventa <code>http://api.flickr.com/services/feeds/photos_public.gne?id=88988666@N00&#038;format=json</code></p>
<p>Interessante poi è la possibilità di utilizzare direttamente il formato PHP e quindi avere già un array precompilato, evitando quindi di dover fare il parsing dei dati. Per farlo basta includere l&#8217;url: (se le impostazioni di sicurezza del server lo permettono)</p>
<pre>
&lt;?php
include("http://api.flickr.com/services/feeds/photos_public.gne?id=88988666@N00&#038;format=php");
print_r($feed); //vediamo l'array fornito da Flickr...
?>
</pre>
<p>Con PHP &ge; 5.2.0 è necessario avere la direttiva <code>allow_url_include</code> impostata a <code>On</code>: Potete verificare tramite il comando <code>phpinfo();</code>. In alternativa potete utilizzare il formato &#8220;php_serial&#8221; &mdash; che ci fornisce l&#8217;array &#8220;serializzato&#8221; &mdash; e il comando <code>unserialize()</code>:</p>
<pre>
&lt;php
$serial = file_get_contents("http://api.flickr.com/services/feeds/photos_public.gne?id=88988666@N00&#038;format=php_serial");
$feed = unserialize($serial);
print_r($feed); //vediamo l'array fornito da Flickr
?>
</pre>
<p>Flickr mette a disposizione feeds per numerose informazioni, basterà cambiare &#8220;photos_public.gne&#8221; con l&#8217;indirizzo che ci interessa. Per approfondire l&#8217;argomento, non mi resta che lasciarvi i link della documentazione di Flickr: <a href="http://www.flickr.com/services/feeds/">http://www.flickr.com/services/feeds/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/08/flickr-feeds/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Twitter API</title>
		<link>http://www.cescopag.com/2008/08/twitter-api/</link>
		<comments>http://www.cescopag.com/2008/08/twitter-api/#comments</comments>
		<pubDate>Sat, 23 Aug 2008 20:54:32 +0000</pubDate>
		<dc:creator>Francesco Paggin</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.cescopag.com/?p=22</guid>
		<description><![CDATA[Se cinguettate su Twitter e volete inserire i messaggi nel vostro sito avete a disposizioni le completissime API. La documentazione la trovate qui ma vi do due dritte al volo&#8230;

Dovete semplicemente utilizzare l&#8217;indirizzo http://twitter.com/statuses/user_timeline/username.format, dove al posto di username metterete il vostro nome utente in Twitter e su format il formato che più vi piace!
Potete [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.cescopag.com/wp-content/uploads/2008/08/269e7d5a-38ca-49f0-8105-3654900f3fab.jpg" alt="269E7D5A-38CA-49F0-8105-3654900F3FAB.jpg" border="0" width="128" height="128" align="right" class="alignright" />Se cinguettate su Twitter e volete inserire i messaggi nel vostro sito avete a disposizioni le completissime API. La documentazione la trovate <a href="http://apiwiki.twitter.com/REST+API+Documentation#StatusMethods">qui</a> ma vi do due dritte al volo&#8230;<br />
<span id="more-22"></span></p>
<p>Dovete semplicemente utilizzare l&#8217;indirizzo <code>http://twitter.com/statuses/user_timeline/<strong>username</strong>.<strong>format</strong></code>, dove al posto di username metterete il vostro nome utente in Twitter e su format il formato che più vi piace!</p>
<p>Potete infatti scegliere tra vari formati per interfacciarvi con Twitter. Se volete gestire il tutto via semplice javascript vi basterà usare il formato <strong>.json</strong>, se avete dimestichezza con l&#8217;xml potete usare appunto il formato <strong>.xml</strong> oppure <strong>.rss</strong> o <strong>.atom</strong> se preferite i classici feed.</p>
<p>In aggiunta potete passare altri parametri, ad esempio <code>?count=NN</code> per prelevare solo gli ultimi NN messaggi (senza questo parametro sono 20), <code>?since=...</code> per prelevare i messaggi da una certa data (in formato HTML date standard), <code>?since_id=ID</code> per prelevare tutti i messaggi dopo un certo ID o infine con <code>?page=N</code> potete passare alle pagine successive.</p>
<p>Utile no? Ad esempio il mio tweeter in rss è:</p>
<p><a href="http://twitter.com/statuses/user_timeline/cescopag.rss">http://twitter.com/statuses/user_timeline/cescopag.rss</a></p>
<p>PS: per sapere come fare il parsing di un xml con php potete leggere <a href="http://www.cescopag.com/2008/05/lastfm-nel-nostro-sito/">il post su last.fm</a></p>
<p>Se invece conoscete jQuery e non volete preoccuparvi del parsing dei dati potete usare questo semplice plugin che si occupa di tutto il necessario, html compreso: <a href="http://tweet.seaofclouds.com/">http://tweet.seaofclouds.com/</a></p>
<p>Che dire, happy twitting!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cescopag.com/2008/08/twitter-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

