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 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.