Come creare un uploader di immagini con jQuery

image

In questo breve tutorial, creeremo un semplice form AJAX di upload basato su jQuery, che permetterà ai visitatori di caricare dei file, un po’ come fatto in questo nostro articolo.

Le funzionalità aggiuntive rispetto al vecchio uploader sono il supporto al drag&drop (ovvero al trascinamento del file sulla finestra del browser) tramite un robustissimo plugin per jQuery, ovvero jQuery File Upload.

Fase 1 – Scheletro HTML

Come al solito, iniziamo con un documento di base, in questo caso HTML5.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Form Upload AJAX!</title>

<link href="assets/css/style.css" rel="stylesheet" />
</head>

<body>

<form id="form" method="post" action="upload.php" enctype="multipart/form-data">
<div id="drop">
Trascina qui!

<a>Carica</a>
<input type="file" name="upl" multiple />
</div>

<ul>
<!-- I file sono mostrati qui -->
</ul>

</form>

<!-- JavaScript Includes -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="assets/js/jquery.knob.js"></script>

<!-- jQuery File Upload e dipendenze -->
<script src="assets/js/jquery.ui.widget.js"></script>
<script src="assets/js/jquery.iframe-transport.js"></script>
<script src="assets/js/jquery.fileupload.js"></script>

<!-- File JavaScript -->
<script src="assets/js/script.js"></script>
</body>
</html>

Prima del tag di chiusura, abbiamo incluso una serie di librerie JavaScript. Questi sono il framework jQuery, il plugin jQuery Knob e le dipendenze per il Plugin jQuery File Upload.

L’elemento principale della pagina è il “divform di caricamento. All’interno c’è il div #drop (che supporta il drag&drop) e una lista non ordinata. Questo elenco conterrà una voce li per ognuno dei file trasferiti.

L’elemento “input” in questo frammento di codice è nascosto tramite CSS. Il suo unico scopo è quello di inizializzare il plugin jQuery Knob, che genera come risultato una bella barra di progresso. Per utilizzarlo, basta passare in ingresso un paio di attributi “data-*” che ne modificano l’aspetto.

In seguito, durante l’upload, aggiorneremo il valore di questo input, il che causerà un aumento della percentuale di progresso.

Fase 2 – jQuery

Ci sono due modi in cui un visitatore può caricare i file in questo form:

  • Trascinando i file sulla finestra (in tutti i browser tranne IE);
  • Cliccando sul pulsante Sfoglia.

Quest’ultimo simulerà un click sul file di input nascosto, che poi mostrerà all’utente la finestra di sfoglia del sistema. Si noti che il file di input ha il set per i parametri multipli, che consentirà all’utente di selezionare più di un file in un colpo solo (i file saranno però caricati singolarmente).

La filosofia su cui si basa il plugin, è quella di inserire i file in una sorta di coda, e faremo in modo che i file caricati compaiano automaticamente nell’elenco che abbiamo scritto nella fase 1.

Ma bando alle ciance, ecco il codice JavaScript:

(function upl($) {

    // Inizializziamo la lista in cui inserire tutti i file caricati
    listone = $(' ul');

    // Funzione per meglio formattare la grandezza di dati
    var formatSize = function (b) {
        if (typeof b !== 'number') {
            return '';
        } if (b >= 1000000000) {
            return (b / 1000000000).toFixed(2) + ' GB';
        } if (b >= 1000000) {
            return (b / 1000000).toFixed(2) + ' MB';
        }

        return (b / 1000).toFixed(2) + ' KB';
    }

    $('#drop a').on('click', function () {
        // Simula il click per mostrare la finestra di dialogo
        $(this).parent().find('input').click();
    });

    // Inizializza jQuery File Upload
    $('#form').fileupload({

        // Designa a quale div assegnare la possibilita' di drag/drop
        dropZone: $('#drop'),
        
        // Permette o meno upload di piu' file
        sequentialUploads: true,

        // Chiamata quando viene aggiunto un file alla coda
        add: function (e, data) {
            // Creo l'input di jQuery Knob
            var knob = $('
');

            // Aggiunge nome e peso del file
            knob
                .find('p')
                .text(data.files[0].name)
                .append('' + formatSize(data.files[0].size) + '');

            // Aggiunge HTML all'elemento UL
            data.context = knob.appendTo(listone);

            // Inizializza il plugin Knob
            knob.find('input').knob();

            // Invia il form automaticamente non appena il file viene aggiunto alla coda
            var jqXHR = data.submit();
        },

        progress: function (e, data) {
            // Calcola la percentuale di completamento dell'upload
            var progress = parseInt(data.loaded/data.total * 100, 10);

            // Aggiorna il campo nascosto e segnala i cambiamenti in modo
            //      che il plugin Knob aggiorni il progresso
            data.context.find('input').val(progress).change();

        },

        // (Eventuale) Qualcosa e' andato storto
        fail: function (e, data) {

        },

        // (Eventuale) Tutto e' andato a buon fine
        done: function (e, data) { }
    });
})(jQuery);

// Preveniamo l'azione di default per gli eventi 'drop' e 'dragover'
document.addEventListener('drop dragover', function (e) {
    e.preventDefault();
});

Come si può notare, ci sono alcune callback che vengono restituite dal Plugin jQuery File Upload ed alcune proprietà particolari. Analizziamo quelle che abbiamo appena usato:

dropZone – Questa proprietà contiene il selettore jQuery dell’elemento che agirà come destinazione dei risultati. Tutti i dati lì rilasciati si aggiungono alla coda.

add – Questa funzione di callback viene chiamata ogni volta che un file viene aggiunto alla coda. Al suo interno, creiamo il markup HTML che rappresenterà il file, lo aggiungiamo alla lista non ordinata e attiviamo il metodo data.submit(). Questo farà sì che il file aggiunto venga caricato direttamente senza aspettare.

progress – Questa callback viene eseguita dal plugin ogni 100ms (configurabili). Il secondo argomento (l’attributo di dati) contiene la dimensione del file e quanti byte sono stati trasferiti. Questo ci permette di calcolare una percentuale, e successivamente aggiornare l’elemento input nascosto, che a sua volta aggiorna lo stato del progresso.

fail – Questa funzione di callback viene eseguito se si verifica un problema con il codice PHP. Ciò significa probabilmente che upload.php non esiste o lancia un qualche tipo di errore (usa l’ispettore del browser per eseguire il debug di eventuali problemi qui).

Consulta l’elenco completo di tutte le opzioni di configurazione disponibili in questa pagina.

Fase 3 – Lo script PHP

Di base, con jQuery File Upload è disponibile anche con uno script PHP robusto per gestire il caricamento di file, ma in questo tutorial, ne costruiremo uno nostro molto più leggero:

<?php

// Una lista delle estensioni permesse
$permessi = array('png', 'jpg', 'gif','zip');

if ( isset($_FILES['upl']) && $_FILES['upl']['error'] == 0 )
{
// Prendiamo l'estensione del file
$ext = pathinfo($_FILES['upl']['name'], PATHINFO_EXTENSION);

// Se l'estensione non e' supportata, restituiamo un errore ed usciamo dalla routine
//
if ( !in_array(strtolower($ext), $permessi) )
{
// Bisogna passare un JSON a jQuery File Upload in modo che
// possa restituire la callback
echo '{"status": "error"}';
exit;
}

// Si crea il file nella cartella 'upload'
if ( move_uploaded_file($_FILES['upl']['tmp_name'], 'upload/'.$_FILES['upl']['name']) )
{
// Restuiamo 'success'
echo '{"status": "success"}';
exit;
}
}

// Bisogna passare un JSON a jQuery File Upload in modo che
// possa restituire la callback
echo '{"status": "error"}';
exit; 

Gli upload dei file inviati dal plugin hanno la stessa valenza di una normale forma di caricamento – ed è quindi possibile accedere alle informazioni relative alle arrivi attraverso il ‘$ _FILES‘.

Come già detto, anche se l’utente è in grado di selezionare un gruppo di file, essi vengono caricati uno per uno. Questo rende ancora più facile da gestire con il nostro script PHP.

Attualmente, i file vengono semplicemente spostati nella cartella “upload“, ma è possibile estendere il tutto aggiungendo l’autenticazione o la creazione di record nel database.

Finito!

Qui è possibile scaricare il sorgente completo di tutto ciò spiegato.

Come creare un semplice breadcrumb in puro CSS3

image

Creare breadcrumb dalla tipica forma a triangolare in puro CSS3 è terribile per almeno 3 motivi:

  1. Gli effetti hover non sono perfetti – il problema sta sulle frecce, poiché sembrano triangoli, ma in verità occupano una regione quadrata. Quindi, cliccando/passando sopra con il mouse sul bordo di un collegamento si potrebbe avviare l’evento sul successivo/precedente;
  2. Non è semplice utilizzare i gradienti ai limiti di ogni link;
  3. Non è semplice animare i collegamenti con frecce che utilizzano transizioni CSS3.

Una possibile soluzione è ruotare il quadrato che giace alla metà interna del link e metà all’esterno, dando quindi una forma triangolare – non solo nell’aspetto ma anche nella funzionalità.

Ma il posizionamento di elementi ruotati è un compito noioso, poiché le dimensioni sono del tutto fuori controllo. Quindi applichiamo un po’ di matematica per ridimensionare il tutto in modo che occupi la stessa altezza dei collegamenti ed in modo che il posizionamento sia semplice.

Questo tutorial utilizza anche i “CSS Counter“, ovvero particolari selettori introdotti con CSS3 che permettono di discriminare i link breadcrumb.

Scheletro HTML

Lo scheletro è un semplice div che raccoglie in sé diversi link.

<div class="bc">
    <a href="#" class="active">Home</a>
    <a href="#">Page</a>
    <a href="#">About Us</a>
    <a href="#">Privacy</a>
</div>

Codice CSS di base

Ecco dove si nasconde la matematica:

.bc {
    display: inline-block;
    box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.35);
    overflow: hidden;
    border-radius: 5px;
    counter-reset: flag;
}

.bc a {
    text-decoration: none;
    outline: none;
    display: block;
    float: left;
    font-size: 12px;
    line-height: 36px;
    color: #FFFFFF;
    padding: 0 10px 0 60px;
    background: #666666;
    background: linear-gradient(#666666, #333333);
    position: relative;
}

.bc a:first-child {
    padding-left: 46px;
    border-radius: 5px 0 0 5px;
}

.bc a:first-child:before {
    left: 14px;
}

.bc a:last-child {
    border-radius: 0 5px 5px 0;
    padding-right: 20px;
}

.bc a.active, .bc a:hover {
    background: #9EEB62;
    background: linear-gradient(#333333, #000000);
}
.bc a.active:after, .bc a:hover:after {
    background: #9EEB62;
    background: linear-gradient(135deg, #333333, #000000);
}

/* La freccia */
.bc a:after {
    content: '';
    position: absolute;
    top: 0;
    right: -18px; /* meta' della lunghezza del quadrato */
    /* stessa dimensione del line-height di .bc a */
    width: 36px;
    height: 36px;
    /* Come vedi, il quadrato ruotato ha una altezza maggiore. Questo è dovuto alla posizione.
     * E' quindi necessario scalare il tutto. Si scala del 70.7% perché:
     *      Teorema di pitagora -> lunghezza = 1; diagonale = (1^2 + 1^2)^0.5 = 1.414
     *        ma la diagonale deve essere pari a 1, quindi lunghezza = 1/1.414 = 0.707
     */
    transform: scale(0.707) rotate(45deg);
    z-index: 1;
    box-shadow:
        2px -2px 0 2px rgba(0, 0, 0, 0.4),
        3px -3px 0 2px rgba(255, 255, 255, 0.1);
    border-radius: 0 5px 0 50px;
    background: #FFFFFF;
    color: #000000;
    transition: all 0.5s;

}

/* Eliminiamo la freccia alla fine dell'ultimo link */
.bc a:last-child:after {
    content: none;
}

/* Usato per mostrare i numeri */
.bc a:before {
    content: counter(flag);
    counter-increment: flag;
    border-radius: 100%;
    width: 20px;
    height: 20px;
    line-height: 20px;
    margin: 8px 0;
    position: absolute;
    top: 0;
    left: 30px;
    background: #FFFFFF;
    box-shadow: 0 0 0 1px #CCCCCC;
    font-weight: bold;
}

Risultato

Come creare una semplice Gallery in puro CSS3

image

Ora che CSS3 è nel suo vivo, la nuova mania è realizzare tutto quel che si può senza usare una riga di JavaScript. Anche se questo comportamento, ai suoi estremi, genera del codice di dubbia leggibilità, è in grado di generare delle fantastiche trovate creative oltre che di valida utilità.

Un esempio di questo modo di fare lo portiamo con questo tutorial sul come utilizzare CSS3 per creare una galleria di immagini con le proprietà relative alle transizione.

Partiamo subito:

Fase 1 – Struttura HTML

Prima di tutto, creiamo un file HTML con la struttura sottostante, che è un fatto da div con id “gal, al cui interno troviamo una lista non ordinata con ogni elemento che contiene due immagini. La prima immagine è la miniatura con una classe “small“, mentre la seconda è l’immagine da visualizzare quando l’evento mouseover, che ha una classe “img”:

<h1>Galleria in CSS3!</h1>
<div id="gal">
<ul>
<li>
<img src="http://imageshack.us/a/img20/1457/78426089.jpg" class="small" width="100" height="100" /><img src="http://imageshack.us/a/img805/5877/76226042.jpg" class="img" />
</li>
<li>
<img src="http://imageshack.us/a/img580/2648/19009737.jpg" class="small" width="100" height="100" /><img src="http://imageshack.us/a/img805/2472/61805791.jpg" class="img" />
</li>
<li>
<img src="http://imageshack.us/a/img15/517/92581088.jpg" class="small" width="100" height="100" alt="" /><img src="http://imageshack.us/a/img703/2600/22697330.jpg" class="img" />
</li>
<li>
<img src="http://imageshack.us/a/img842/8881/68478078.jpg" class="small" width="100" height="100" alt="" /><img src="http://imageshack.us/a/img18/931/89993020.jpg" class="img" />
</li>
<li>
<img src="http://imageshack.us/a/img24/4710/68180029.jpg" class="small" width="100" height="100" /><img src="http://imageshack.us/a/img845/6489/30701469.jpg" class="img" />
</li>
</ul>
</div>

Fase 2 – Un tocco di stile e di animazioni!

Adesso buttiamo in gioco la vera anima del tutorial, ovvero il CSS. Molto semplicemente, diamo uno stile molto dubbio allo sfondo ed alla galleria e nascondiamo l’immagine grande.

In secondo luogo, specifichiamo l’effetto transition e quello di animazione alla seconda immagina e le attivismo non appena l’utente passa con il mouse sull’immagine di anteprima:

h1 {
    color: #FFFFFF;
    font-size: 3em;
    text-shadow: #333333 2px 2px 4px;
}

#gal {
    background: #333333;
    border: 5px solid #111111;
    border-radius: 20px;
    margin-left: auto;
    margin-right: auto;
    overflow: visible;
    height: 300px;
    width: 500px;
    filter: progid:DXImageTransform.Microsoft.Shadow(color='#333333', Direction=135, Strength=10);
    box-shadow: #333333 15px 25px 200px;
}

#gal ul {
   margin-left: -15px;
}

#gal ul li {
    display: inline-table;
    list-style: none;
    padding: 15px;
}

#gal ul li .img {
    border: 1px solid #000000;
    box-shadow: #333333 5px 5px 10px;
    margin-top: -50px;
    margin-left: -50px;
    position: absolute;
    opacity: 0;
    visibility: hidden; filter:progid:DXImageTransform.Microsoft.Shadow(color='#333333', Direction=135, Strength=5);
  
    -webkit-transition: all 0.4s ease-in-out;
    -moz-transition: all 0.4s ease-in-out;
    -o-transition: all 0.4s ease-in-out;
    transition: all 0.4s ease-in-out;
}

#gal ul li:hover .img {
    float: right;
    height: 300px;
    opacity: 1;
    width: 300px;
    visibility: visible;
}

Finito! Ecco il risultato usabile su CodePen:

Come ordinare oggetti JSON con jQuery

image

In ufficio, stiamo lavorando ad una applicazione web che esegue una ricerca su un vasto campi di input che filtrano la ricerca. Una volta inviato il form, l’applicazione (nello specifico, una funzione in PHP), restituisce un risultato in JSON.

Per ordinare il risultato via front-end, si è deciso di prendere una proprietà numerica da un oggetto, e quindi ordinare facendo confronti a due su questi valori. Il JSON che ne è venuto fuori è qualcosa del genere:

[{
"proprieta": dati1,
"ordine": 1
},
{
"proprieta": dati,
"ordine": 8 },
{
"proprieta": dasa,
"ordine": 2 }]

Dunque, l’obiettivo è farsi restituire tutti questi dati e manipolarli in modo che vengano ordinati per ‘ordine’ crescente. Poiché l’ordinamento deve avvenire solo e soltanto quando PHP ci ritorna il JSON, si rivela particolarmente utile il $.ajax di jQuery:

(function ($) {
    $('#selettore').on('click', function () {
        $.ajax({
            url: 'url/script.php',  // indirizzo dello script in PHP
            data: null,             // Non passiamo nulla
            dataType: 'json',       // Esplicito il tipo di dato di ritorno
            type: 'GET',

            success: function (data) {
                // Ordiniamo i dati restituiti con la classica funzione di ordinamento
                var ord = data.sort(function (n1, n2) {
                    if (n1.ordine > n2.ordine) {
                        return 1;
                    }
                    if (n1.ordine < n2.ordine) {
                         return -1;
                    }

                    return 0;
                });
               
                // Assegnamo la stringa che conterra' tutto l'insieme
                var string = '';
                
                // Concateniamo a string il tutto
                ord.each(function (index, val) {
                    string += ', ' + val.ordine;   
                });
                
                // Mostriamo il risultato nel tag con id 'risultato'
                $('#risultato').text(string); // 1, 2, 8
            },
            
            error: function (xhr, status, text) {
                console.log(status + ' ' + text);
            }
        });
    });
})(jQuery);

Per attuare questa semplice e indolore tecnica, è necessario che lo script lato server sia progettato per restituire un array di oggetti, piuttosto che di un elenco di oggetti.

Come installare Compass.app su Ubuntu gratuitamente

compass.app

Sto usando SASS e Compass da più di un anno ormai, e sono giunto alla conclusione che è una delle migliori soluzioni attualmente esistenti in grado davvero di potenziare e portare ad un livello successivo le capacità di scrivere codice CSS semplice e leggibile. Alcune delle sue caratteristiche chiave come selettori annidati, variabili, mixin e funzioni sono davvero preziose per me.

Installare ed iniziare subito ad usare SASS e Compass è abbastanza semplice e facile su Ubuntu o qualsiasi altro sistema operativo, come ad esempio usarlo in combinazione con Sublime Text 2 in Windows, e bastano due righe su terminale per far compilare automaticamente il codice. Tuttavia, avere una interfaccia grafica che velocizzi quei comandi per noi può essere utile.

Una fra queste è Compass.app, è una applicazione scritta in Java (JRuby) in modo che possa essere eseguito su Linux, Mac e Windows. L’applicazione in sé non è gratuita, ma dal momento che gli sviluppatori hanno reso il codice open-source, è possibile compilare legalmente la propria copia scaricando il sorgente dal loro repo git.

Ecco come compilare Compass.app

1. Assicurarsi di avere il JDK ufficiale o open-jdk installato lanciando uno dei seguenti comandi da terminale:

sudo apt-get install openjdk-6-jdk

oppure

sudo apt-get install openjdk-6-jdk

2. Scaricare l’ultima versione di JRuby da qui ed estrarlo nella cartella home, quindi rinominare la cartella “jruby”;

3. Aprire il terminale (Ctrl+Alt+T) e digitare il comando seguente per aggiungere JRuby al percorso di sistema:

echo PATH=\$PATH:\$HOME/.jruby/bin >> .bashrc

4. Aprire un nuovo terminale ed eseguire il seguente comando per installare Rawr Package Manager:

jruby -S gem install rawr --source http://gems.neurogami.com

5. Clonare la fonte Compass.app da GitHub:

git clone git://github.com/handlino/CompassApp.git "CompassApp"

o se git non è installato, utilizzare il seguente comando per installarlo:

sudo apt-get install git

6. Cambiare la directory corrente passando alla cartella CompassApp con:

cd CompassApp

7. Infine compilare CompassApp:

jruby -S rake rawr:bundle:all

Una volta che la compilazione è conclusa, è necessario spostare il risultato della compilazione all’interno di CompaassApp/packages/linux ed eseguire il file run.sh per avviare l’applicazione. Per velocizzare il tutto, è possibile caricare ed eseguire questo script all’interno della cartella CompaassApp/packages/linux.

In breve, lo script sposta la cartella compass.app e crea un collegamento al desktop per accedere Compass:

mv compass.app ~/.compass.app;

{ echo [Desktop Entry];
echo Type=Application;
echo Name=Compass.App;
echo Comment=Compass.App;
echo Icon=$HOME/.compass.app/lib/images/icon/512.png
echo Exec=.compass.app/run.sh;
echo Terminal=false;
echo Categories=Development\;;
echo StartupWMClass=Compass; } >> ~/.local/share/applications/CompassApp.desktop;

chmod +x ~/.local/share/applications/CompassApp.desktop;

Via | solancer