L’Oscura Arte del Drag and Drop: Come Trascinare e Rilasciare Oggetti?
Quella di trascinare e rilasciare oggetti in una pagina web è una proprietà molto affascinante e di sicuro effetto. Chi ha familiarità con il pannello di amministrazione di WordPress saprà ad esempio che per attivare un widget, basta trascinarlo sulla sidebar nella posizione desiderata. Questo rende certamente molto semplice ed intuitiva tale operazione. In questo articolo apprenderemo le basi di questa procedura piuttosto complessa, ma che grazie a jQuery si trasforma in un gioco da ragazzi. L’idea ti stuzzica? Addentriamoci dunque nella lettura dell’articolo.
Le user interface di jQuery, una risorsa di enorme valore
Le User Interface (UI) sono una raccolta di solide estensioni che aiutano nella risoluzione di problemi piuttosto comuni. Possiamo ad esempio (tramite una riga di codice), installare un datepicker (sono quei piccoli calendari che compaiono nei form quando dobbiamo inserire una data) altamente configurabile sia nell’estetica sia nella funzionalità: vedere per credere.
Di questa raccolta fanno parte i metodi draggable() e droppable() che andremo ora ad analizzare nel dettaglio.
Prima di iniziare, dai uno sguardo alla pagina di esempio. Come puoi vedere si tratta di una pagina con cinque elementi:
- Un contenitore (sulla destra) che rappresenta l’area nella quale gli elementi potranno essere rilasciati.
- Un elemento non trascinabile.
- Un elemento trascinabile ma il cui rilascio nell’area a destra non viene intercettato.
- Un elemento trascinabile (unicamente sull’asse orizzontale) il cui rilascio viene intercettato.
- Un elemento trascinabile che durante il trascinamento diventa opaco, il cui rilascio viene intercettato, ed una volta rilasciato rimane “incollato” al contenitore. Se notate l’elemento precedente, una volta rilasciato, viene intercettato; ma in seguito è ancora possibile riposizionarlo anche fuori dal contenitore.
Quanto hai visto è quello che stiamo per fare insieme. Iniziamo come sempre ad impostare la pagina html.
Preparariamo la pagina
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> <script type="text/javascript"> $(document).ready(function(){ // qui scriveremo il codice jQuery }); </script> </head> <body> </body> </html>
Adesso inseriamo nel body del documento i quattro elementi di sinistra e l’area di rilascio a destra.
<div id="container"> <div id="left_block"> <div class="non_trascinabile box"> <p>NON TRASCINABILE</p> </div> <div class="trascinabile box"> <p>TRASCINABILE</p> </div> <div class="trascinabile_rilasciabile rilasciabile box"> <p>TRASCINABILE E RILASCIABILE</p> </div> <div class="non_reversibile rilasciabile box"> <p>TRASCINABILE RILASCIABILE E NON REVERSIBILE</p> </div> </div> <div id="right_block"> </div> </div>
Come vedi, all’interno dell’elemento #left_block dichiaro i quattro elementi. Nota le classi applicate ad ognuno di essi; la classe box è quella che ne definisce l’aspetto, mentre le altre serviranno per definirne le proprietà (vedremo in seguito) del trascinamento.
Andiamo ora a scrivere il CSS nel file screen.css
#container{ margin: 0 auto; width: 960px; } #left_block{ float: left; } #right_block{ float: right; width:300px; height: 300px; border: 10px solid gray; } .box{ background-color: #00AAFF; width: 200px; padding: 15px; text-align: center; margin-bottom: 10px; } .hover{ background-color: #FFFFD4; }
Inoltre centro il contenuto all’interno di un contenitore, posiziono gli elementi e gli attribuisco un minimo di stile.
Tra poco vedremo cosa definisce la classe hover.
Nell’header del nostro documento dobbiamo ancora richiamare jQuery e le estensioni che costituiscono le user interface, contenute nel file jquery-ui-1.7.2.custom.min.js.
Inoltre includeremo il foglio di stile screen.css che abbiamo precedentemente creato.
<link href="screen.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.7.2.custom.min.js"></script>
Possiamo dare uno sguardo al documento che ora dovrebbe presentarsi così
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> <link href="screen.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="js/jquery-1.3.2.min.js"></script> <script type="text/javascript" src="js/jquery-ui-1.7.2.custom.min.js"></script> <script type="text/javascript"> $(document).ready(function(){ }); </script> </head> <body> <div id="container"> <div id="left_block"> <div class="non_trascinabile box"> <p>NON TRASCINABILE</p> </div> <div class="trascinabile box"> <p>TRASCINABILE</p> </div> <div class="trascinabile_rilasciabile trascinabile box"> <p>TRASCINABILE E RILASCIABILE</p> </div> <div class="non_reversibile trascinabile box"> <p>TRASCINABILE RILASCIABILE E NON REVERSIBILE</p> </div> </div> <div id="right_block"> </div> </div> </body> </html>
A questo punto la pagina dovrebbe apparire come in questo esempio.
Ora che abbiamo concluso la preparazione, passiamo finalmente alla realizzazione del codice per attivare le funzionalità di trascinamento e rilascio degli oggetti.
Come rendere un elemento “droppabile” (rilasciabile)
La prima cosa che faremo sarà rendere il blocco di destra un’area dove è possibile rilasciare un oggetto utilizzando il metodo droppable().
Tutti i blocchi di codice che aggiungeremo ora, vanno scritti all’interno della funzione principale.
$("#right_block").droppable({ accept: '.rilasciabile', hoverClass: 'hover', tolerance: 'fit', drop: function(event, ui){ ui.draggable.find('p').html('rilasciato!'); } });
Vediamo cosa significa questo codice:
- nella prima riga diciamo di rendere droppabile l’elemento con id right_block.
- In seguito passiamo una serie di parametri il primo dei quali è accept. Nel nostro caso è valorizzato con .rilasciabile; ciò significa che sarà possibile rilasciare unicamente gli elementi con classe rilasciabile.
- Il secondo parametro è hoverClass. Definisce la classe CSS da applicare quando l’elemento trascinato si trova sopra l’area di rilascio. Nella fattispecie, la classe hover che abbiamo definito precedentemente e che modifica il colore del background. Segnalare quando un elemento è in zona utile per il rilascio è una questione di usabilità.
- Il terzo parametro è tolerance e definisce la circostanza nella quale un elemento è da considerarsi in zona di rilascio. Abbiamo quattro possibilità:
- fit: quando tutto l’elemento trascinato è all’interno dell’area rilasciabile.
- pointer: quando il puntatore del mouse è all’interno dell’area rilasciabile;
- touch: quando l’elemento trascinato tocca l’area rilasciabile;
- intersect: quando almeno la metà dell’elemento trascinato si trova all’interno dell’area rilasciabile;
- Infine, con il parametro drop possiamo definire la funzione da eseguire al momento del rilascio. In questa funzione, il parametro che abbiamo definito con ui, diventerà l’oggetto che ci permetterà di manipolare e accedere all’elemento trascinato ed infine rilasciato al quale ci si potrà riferire con ui.draggable. Noi semplicemente ci limiteremo a sostituire la scritta contenuta nell’elemento.
ui.draggable.find('p').html('rilasciato!');
Questa riga di codice riportata sopra significa: nell’elemento appena rilasciato, trova il tag p e sostituisci il contenuto di questo tag con la scritta “rilasciato!”.
Come rendere gli elementi trascinabili?
Per rendere trascinabile un oggetto non dobbiamo fare altro che applicarvi il metodo draggable() che ora andremo ad analizzare. Iniziamo quindi con l’applicare il metodo draggable() all’elemento con classe “trascinabile” (secondo elemento) in questo modo:
$(".trascinabile").draggable();
Se provi ora il tuo script, vedrai che questo elemento è diventato trascinabile e può essere posizionato ovunque. Ma trascinandolo sull’area di rilascio non succede nulla, perché?
Abbiamo definito che solo gli elementi aventi classe rilasciabile possono essere rilasciati e non è il caso di questo elemento.
Come rendere gli oggetti trascinabili su un unico asse?
Passiamo ora al terzo elemento.
$(".trascinabile_rilasciabile").draggable({ axis: 'x' });
L’abbiamo reso trascinabile ed abbiamo aggiunto la proprietà axis impostata su x. Ciò significa che questo elemento è trascinabile unicamente sull’asse orizzontale. Non vi era nessuna necessità di assegnare questa impostazione, l’ho fatto per puro scopo didattico e mostrarti con quale semplicità si può ulteriormente personalizzare il trascinamento.
Se entriamo nell’area di rilascio con questo elemento, vedremo il colore del background cambiare, e se lo rilasciamo potremo notare che la scritta si modifica, a testimoniare che l’evento è stato intercettato.
In questo caso però, se provi a trascinare l’elemento all’esterno dell’area, ti renderai conto che questa operazione è possibile.
Ma cosa dobbiamo fare in caso volessimo che l’elemento rilasciato rimanga in qualche modo legato al contenitore?
Come trascinare un elemento e legarlo al contenitore dopo il rilascio?
Applichiamo questa proprietà all’ultimo elemento:
$(".non_reversibile").draggable({ opacity: 0.5, revert: 'invalid' });
Abbiamo impostato il parametro opacity su 0.5. Questo significa che durante il trascinamento, l’oggetto diventerà opaco. Anche in questo caso è stata utilizzata questa proprietà per puro scopo didattico.
Ma quello che veramente ci interessa è il parametro revert impostato su invalid. In questo modo, una volta rilasciato l’elemento non sarà più possibile trascinarlo all’esterno. Un altro effetto di questa impostazione è che, qualora l’elemento venisse trascinato e rilasciato all’esterno dell’area preposta, esso si riposizionerà nel punto di partenza.
Ecco la funzione completa
$(document).ready(function(){ $(".trascinabile").draggable(); $(".trascinabile_rilasciabile").draggable({ axis: 'x' }); $(".non_reversibile").draggable({ opacity: 0.5, revert: 'invalid' }); $("#right_block").droppable({ accept: '.rilasciabile', hoverClass: 'hover', tolerance: 'fit', drop: function(event, ui){ ui.draggable.find('p').html('rilasciato!'); } }); });
Conclusione
In questo articolo abbiamo visto le basi di una tecnica che ci permette di aggiungere delle funzionalità dinamiche e di effetto ai nostri siti. Io ho utilizzato il drag and drop nel pannello di amministrazione di un sito nel quale, tutto quello che è eliminabile, può essere trascinato nel cestino (utenti, contenuti, ecc), qualcosa del genere.
Dal lato utente, un’applicazione diffusa è il “carrello della spesa“; funzionalità della quale puoi vedere un esempio molto raffinato realizzato con jQuery e con i principi che abbiamo visto in questo articolo.
E tu lo utilizzi? Puoi farci degli esempi concreti di come hai applicato o come potresti applicare questa tecnica?
29 commenti
Trackback e pingback
Non ci sono trackback e pingback disponibili per questo articolo
ottima come spiegazione. Io ho provato ad utilizzare il drag and drop in passato per ordinare le righe di uan fattura in un gestionale ma avevo utilizzato prototype e non jquery.
Le UI di jquery di aprono a molte interessanti funzionalità.
L’esempio che hai mostrato del carrello della spesa è molto bello e di facile utilizzo.
Grazie Luca! :-)
Gran bell’articolo Maurizio!
Non ho ancora avuto modo di utilizzare il drag and drop in nessuno dei miei progetti, ma credo che per la gestione di alcune pratiche di back-end siano la cosa più indicata perchè rendono molto più intuitiva l’azione da svolgere (vedi la gestione dei widget di wp e la gestione dei menù di navigazione nella nuova versione) agli utenti che non hanno grandi competenze tecniche.
Come utilizzo in ambito back-end ultimamente ho visto il pannello di amministrazione di uno script realizzato per la gestione di un’agenzia immobiliare che permetteva di ordinare le foto inserite nei vari annunci mediante drag and drop. Idem per l’ordinamento e la posizione di alcuni box visualizzati sulla home del front-end, come per esempio la sezione annunci, offerte, ecc.
Ciao Nando e grazie.
In effetti l’ordinamento di oggetti possiamo immaginarlo come un caso particolare di drag and drop per il quale jQuery mette a disposizione il metodo sortable(), che dovrebbe risolvere con semplicità questo tipo di applicazione.
http://jqueryui.com/demos/sortable/
Ottimo articolo! molto utile.
Grazie Luigi!
Ottimo articolo e argomento Maurizio, mi già capitato di lavorare con la UI di jQuery ed in particolare appunto con i loro metodi draggable e droppable.
Gli ho trovati veramente fantastici, la facilità di utilizzo e la OTTIMA documentazione sono state fondamentali !!!
Complimenti per l’articolo :)
Ciao Nicolas e grazie. In effetti il grande successo di jQuery passa anche da una documentazione dettagliata e da esempi chiari.
Grande Maurizio… Un bell’ articolo.
Trovo molto affascinante la libreria di jQuery UI.
Ho realizzato un sito con questa libreria e mi sono divertito tantissimo ad usarlo. Se vuoi pui dargli un’occhiata:
Mefop
L’utente si puo personalizzare la home page come meglio crede.
Complimenti per l’articolo.
Ciao melaS. Davvero bello questo sito. Come tieni traccia della disposizione che l’utente sceglie? crei un cookie?
Vorrei dare la possibilità ai visitatori dei miei siti di personalizzare la disposizione dei vari elementi da front end, esattamente quello che ha fatto melaS. Lavoro con WordPress versione 3.0 e successive su diversi siti, ma non mastico molto codice… Non esiste un plugin che inserisca il codice dove necessario e che chieda gli altri parametri nella configurazione?
Esatto, si crea un cookie in modo da memorizzare le scelte del cliente… e poi c’è la possibilità di cancellare i cookie e tornare alla home page originale con i widget pre-stabiliti.
Caro Maurizio,
grazie per il tutorial, come sempre utilissimo e chiarissimo.
Ho trovato un’applicazione dei metodi draggable and droppable a questo indirizzo:
http://www.shmotter.com/studio
Aspetto il prox tutorial … :)
Ciao,
Francesco
Grazie Francesco.
La pagina che hai indicato utilizza proprio jQuery ed i metodi che abbiamo visto nell’articolo
Ciao, molto interessante l’articolo, tuttavia ho bisogno di farti una domanda… se io volessi ottenere questa cosa con il d&d:
oggetto –> trascino l’oggetto in un box –> si attiva un link associato all’oggetto che viene automaticamente richiamato all’atto del “rilascio” dell’oggetto nel box.
Come potrei fare?
Grazie mille
Andrea
Non sono sicuro di avere capito bene, ma comunque la prima cosa che mi passa per la testa è la seguente.
Ad ogni link che vuoi aprire viene associato un id, che a sua volta viene associato all’oggetto.
Al momento del rilascio si legge l’id dell’oggetto rilasciato e si richiama il relativo link (document.location.href=link)
Ciao maurizio, grazie per la risposta. Effettivamente è una cosa un pochetto strana, mi sembra di averla vista da qualche parte in giro per la rete, ma non sono mai riuscito a rifarla. Ovviamente il sito non me lo ricordo.
E’ una sorta di “menu” ad oggetti dove i link si attivavano trascinandoli (trascinando l’oggetto associato a quel link) in un box… una cosa un po’ strana, ma molto divertente da provare e vedere…!
Ora vediamo se riesco con lo spunto che mi hai dato.
Ciao
a
ciao! la tua spiegazione è molto chiara,solo che nn riesco a farli muovere come dovrebbero,mi rimangono in blocco,ho provato un sacco di volte! io ho copiato le varie parti di codice ,ma il movimeto nn me lo attiva …grazie ,(avrai capito che sono alle prime armi^^)
Caro Maurizio,
ho visto solo ora il tuo sito cercando qualcuno che mi spiegasse come implementare un drag&drop . Ti anticipo che sono davvero un profano (ho creato, con fatica…eheh, il sito di mia moglie) e ora dovrei impostare un piccolo shop per le sue pietre zodiacali. Pensavo appunto alla tecnologia drag&drop e così ho provato a replicare (proprio il tuo esempio, per imparare un po’) quanto tu spieghi sulla tua homepage. Purtroppo quando lancio la preview per vedere il risultato (uso Firefox come browser e dreamweather come designer) non ottengo alcun trascinamento (non appare nemmeno il cambio di cursore) ne di rilascio. Ma non è che questa proprietà si attiva solo se copio il tutto sul web server del mio provider ? (mi sembra strano ma casomai è proprio così…).
Grazie 1000 in anticipo Maurizio. TI auguro buone Feste ed un inizio di 2012 “scoppiettante”!!!
Ernesto
Ciao Ernesto,
da profano a profano….
hai scaricato la libreria JQuery sul tuo pc e messo la cartella “js” nella stessa cartella dove si trovano i tuoi files??Luca
Ciao Maurizio grandioso tutorial! Finalmente posso mettere mano (o per lo meno lo spero!) a cio’ che avevo in mente da un annetto: fare drag & drop su una matrice per interagire con un DB.
Sono partito dal caso piu’ semplice ovvero cambiando di posto l’elemento A dalla posizione 1×2 alla posizione 2×1 in una matrice 2×2.
Facendo un po’ di prove ho notato che volta spostato e rilasciato un elemento sopra l’altro mi ritrovo con il posto 1×2 senza id e due id sovrapposti nel posto 2×1. Giustamente…
Supponendo di non voler ricaricare la matrice ad ogni drop ho pensato che potrebbe essere il caso di traspostare solo gli attributi dell’id 1×2 per poi riversarli nell’id 2×1.
Come potrei approcciare al problema?
Ciao. Bellissimo tutorial!
Ma su ie non funziona. Consigli?
Grazie
Ciao Francesca e grazie.
Con che versione di ie lo stai testando? Io l’ho appena testato con la 9 e funziona benissimo.
Eventualmente prova a mettere l’ultima versione di jquery e delle ui
Io sto cercando di creare in jquery un filetto (o anche tris… ha diversi nomi) e questo tuo articolo mi è stato molto utile.
Spero di riuscire a finirlo presto e poterlo mettere sul mio sito
Scusa… sto cercando di sviluppare il gioco del filetto in JS e sono arrivato ad avere l’esigenza di dover liberare il div drop di partenza per arrivare ad un secondo di arrivo… Non so se mi sono spiegato.
In pratica dovrei sapere qual’è il div di partenza per sbloccarlo, una specie di DIP, potrei definirlo… Mi sai aiutare??? TNX
Ho provato a generare una pagina.
Ritengo che l’utilizzo dei box trascinabili sia interessante per la gestione dei menè
vorrei sapere come posso partire con la deposizione dei primi box al centro della pagina e poi allargare la fila orizzontale dei blocchi fino a riempire la prima riga
Di qui passare alla riga successiva senpre partendo dal centro……..
Ogni blocco contiene una voce del menu’ consentendo all’operatore di risitemare le voce a suo piacimento
Molto chiaro l’artciolo e talmente accattivante che ho adottato il sistema per scrivere un menu formato da tantio box colorati uno per ogni voce del menu.
Con la funzione da te illustrata l’utente puo’ spostare i boxes organizzandosi il menu come meglio crede…
Adesso correi capire come posso fare si che la posizione dei boxes possa essere memorizzata in modo che al richiamo della pagina l’utente la ritrovi come l’aveva lasciata e non nella posizione originale
Questo è importante in quanto quando viene chiamata una voce del menu la pagina viene sostituita per cui quando l’utente ritorna alla pagina padre dovrebbe ritrovarla come l’ha lasciata.
Spero di essere stato chiaro
Grazie per ora.
Roberto Valentini
Articolo molto utile e ben fatto, come tutti quelli interni al vostro sito… Volevo solo chiedere se con lo stesso metodo, era possibile fare in modo di cambiare la classe o id dell’elemento droppabile a seconda della classe o id dell’elemento draggabile rilasciato… spero di essermi spiegata,
un saluto
grazie mille
Salve,
Come potrei ottenere che l’elemento appena viene droppato all’interno del contenitori si sistemi in alto e gli altri eventuali dopo di lui si sistemino uno sotto l’altro ??
Grazie