Una delle nuove funzionalità di HTML5 è il drag and drop nativo. Sorprendentemente, Internet Explorer ha avuto il supporto per il drag and drop nativo dalla versione 5.5; in effetti, l'implementazione HTML5 si basa sul supporto di IE. Nel tutorial di oggi, vedremo come implementare il drag and drop nativo per creare una semplice interfaccia per il carrello degli acquisti.
Ecco cosa costruiremo: è un carrello di base con un pannello di prodotti e un pannello di carrelli. Per "acquistare" un prodotto, sarai in grado di trascinarlo dal pannello al carrello; manterremo una traccia della quantità e rimuoviamo gli articoli dal pannello del prodotto quando sono esauriti.
Nota che in realtà non stiamo costruendo un carrello della spesa qui; non lavoreremo con nessuna bontà sul lato server oggi. Questo è solo il front-end; il punto è il drag and drop HTML5.
Certo, inizieremo con l'HTML; ecco il nostro guscio:
Trascina e rilascia il carrello acquisti
Piuttosto basico: stiamo collegando un foglio di stile e jQuery; utilizziamo solo jQuery per gestire facilmente eventi e manipolazioni DOM; il drag and drop sarà nativo. Tuttavia, siamo di fronte a un muro qui, perché il trascinamento della selezione HTML5 aggiunge alcune proprietà all'oggetto evento. JQuery non usa l'oggetto evento predefinito; crea il proprio per equalizzare i problemi dell'oggetto evento. Per questo motivo, non otteniamo le proprietà speciali con l'oggetto evento di jQuery. Ma non preoccuparti; c'è un plugin per questo; stiamo trascinando il Native Drag and Drop per far funzionare tutto. Infine, includeremo il nostro script: dragdrop.js
.
Ora siamo pronti per aggiungere alla nostra lista di prodotti; per le immagini dei prodotti, sto usando icone del Superpack Icon Apple, creato da SvenVath. (Ho rinominato le icone con nomi più semplici e li ho ridimensionati a 180 px.)
Inserisci ul # prodotti
come il primo figlio all'interno del corpo. Una volta fatto, esamineremo il primo elemento dell'elenco:
iMac
Prezzo: $ 1199,00
Quantità: 10
Abbiamo estratto l'oggetto della lista, con un'ancora all'interno; nota che ogni oggetto di ancoraggio avrà una classe di articolo
(importante quando arriviamo al CSS) e un ID personalizzato (importante quando arriviamo al JavaScript). Quindi, l'ancora ha anche il trascinabili = "true"
attributo; questo dovrebbe essere tutto ciò di cui abbiamo bisogno per rendere l'elemento trascinabile (vedremo presto alcuni avvertimenti). Stiamo usando un tag di ancoraggio qui in modo da poter fare qualcosa per i browser senza supporto nativo per il drag and drop (anche se non lo faremo qui). Poi abbiamo l'immagine del prodotto e un div con le informazioni sul prodotto. E sì, è necessario avvolgere il prezzo e la quantità con campata
Ecco il resto degli elementi dell'elenco:
i phone
Prezzo: $ 199.00
Quantità: 16
AppleTV
Prezzo: $ 299.00
Quantità: 9
Cinema Display
Prezzo: $ 899.00
Quantità: 4
Ipod nano
Prezzo: $ 149.00
Quantità: 20
Macbook
Prezzo: $ 1199,00
Quantità: 13
Mac Mini
Prezzo: $ 599.00
Quantità: 18
C'è un ultimo pezzo di HTML: il carrello della spesa:
Carrello della spesa
Totale: $0.00
Rilascia qui per aggiungere al carrello
E questo è il nostro HTML!
Idealmente, tutto ciò che dovresti fare per rendere un elemento trascinabile è impostare l'attributo trascinabile su true; tuttavia, c'è dell'altro. Per far funzionare le cose correttamente, devi impostare alcune cose in CSS. Innanzitutto, pensa a questo: cosa fa clic e trascina su elemento "normale" (non trascinabile)? Di solito, seleziona il testo. Quindi, vogliamo assicurarci di trascinare l'elemento, e non solo il suo contenuto. Per far fronte a, è necessario utilizzare il seguente CSS:
[draggable = true] -moz-user-select: none; -webkit-user-select: none; -webkit-user-drag: element;
Per comodità, il plug-in di trascinamento nativo che utilizziamo imposta queste proprietà per noi, in modo che possiamo lasciarle fuori se vogliamo. Tuttavia, lo faremo:
[draggable = true] cursor: move;
Iniziamo lo styling:
html height: 100%; body background: #ececec; margin: 0; padding: 0; font: 13px / 1.5 helvetica, arial, san-serif; altezza: 100%; h1, h2 text-align: center; h2 position: absolute; fondo: 20px; color: #fff; text-shadow: 0 0 10px rgba (0, 0, 0, 0,75); display: none; p margin: 0;
Dato che non stiamo usando un reset completo, ecco il nostro pseudo-reset. Dovrebbe essere tutto auto-esplicativo. Stiamo impostando l'altezza al 100% sul html
e corpo
elementi perché vogliamo #carrello
essere l'intera altezza dello schermo; per fare ciò, ogni elemento genitore deve avere la sua altezza impostata al 100%. Inoltre, nota che stiamo usando rgba per impostare il colore dell'ombra; se un browser non supporta questo, non ci sarà un'ombra sul h2
. E stiamo nascondendo questo h2
IMPOSTANDO display: nessuno
. Ricorda il h2
dice "Rilascia qui per aggiungere al carrello", quindi lo faremo sfumare quando il trascinamento inizia e si dissolve quando termina la resistenza.
Passando alla nostra lista prodotti ...
#products float: left; list-style: none; width: 65%; padding: 0; #products li display: inline;
Di nuovo, abbastanza ovvio. La cosa importante in questo frammento è che gli elementi della lista saranno visualizzati in linea. Dal momento che stabiliremo blocco di visualizzazione; float: sinistra
sugli ancoraggi, IE darà agli elementi della lista un effetto "gradini"; possiamo aggirare questo bug impostando display: in linea
sull'elemento padre dell'ancora.
A proposito delle ancore, modelliamole accanto.
.item display: block; float: sinistra; larghezza: 180px; altezza: 180px; margin: 10px; border: 1px solid # 494949; text-align: center; text-decoration: none; colore: # 000; overflow: hidden; .item img border: 0; margine: 10px auto; larghezza: 160px; altezza: 160px; .item div background: rgb (0, 0, 0); background: rgba (0, 0, 0, 0.5); position: relative; bottom: 69px; color: # f3f3f3; imbottitura: 5px 0; display: none;
Ogni ancoraggio sarà stilizzato come una scatola 180x180px; questo sarà riempito con l'immagine del prodotto. Il div informazioni prodotto verrà posizionato sopra l'immagine, nella parte inferiore del quadrato. Si noti che dobbiamo impostare un colore di sfondo e quindi resettarlo per i browser moderni, perché IE non supporta RGBa. Stiamo ambientando display: none
su questa informazione div così possiamo sbiadirla dentro e fuori quando il "cliente" si aggira e si spegne, rispettivamente.
Tutto ciò che resta da stile è il carrello della spesa; lo vedremo qui, ma, ricorda, gli elementi della lista saranno inseriti da jQuery in seguito, quindi non vedrai che questo sta accadendo ancora.
#cart float: right; background-color: #ccc; width: 25%; imbottitura: 0 5%; height: 100%; #cart ul padding: 0; #cart li list-style: none; border-bottom: 1px solid # 494949; padding: 5px; #cart .quantity font-weight: bold; padding-right: 10px; margin-right: 10px; border-right: 1px solid # 494949; display: inline-block; larghezza: 15px; text-align: right; #cart .price float: right; #totale float: right;
Elementi con le classi quantità
e prezzo
sarà all'interno degli elementi di elenco inseriti dinamicamente.
Questo è tutto per i CSS; prima di passare alla stella di questo spettacolo, diamo un'occhiata al nostro lavoro finora.
Siamo arrivati a JavaScript; secondo il medico HTML5:
HTML 5 DnD è basato sull'implementazione originale di Microsoft, disponibile già in Internet Explorer 5! Ora attualmente supportato in IE, Firefox 3.5 e Safari 4.
Ecco un elenco degli eventi che HTML5 trascina e rilascia offerte:
Non li useremo tutti, ma vedremo come funzionano la maggior parte di loro.
Innanzitutto, lavoreremo con i nostri prodotti:
$ ('. item') .bind ('dragstart', function (evt) evt.dataTransfer.setData ('text', this.id); $ ('h2'). fadeIn ('fast');) .hover (function () $ ('div', this) .fadeIn ();, function () $ ('div', this) .fadeOut (););
Iniziamo afferrando tutti gli oggetti; quindi, associamo una funzione al dragstart
evento; questo evento si attiva quando iniziamo a trascinare l'evento. La prima cosa che faremo quando un oggetto viene trascinato è impostare alcuni dati; in realtà, se non è impostato alcun dato, firefox non lascerà trascinare l'elemento. Speciale per trascinare gli eventi è una proprietà dell'oggetto sull'oggetto evento chiamato trasferimento dati
; useremo due metodi di questa proprietà: setData
e getData
. Qui, stiamo usando il setData
metodo, che prende due parametri: un formato dati e i dati. Useremo il tipo di dati 'testo'. Quindi, imposteremo i dati come id dell'elemento che l'utente sta trascinando. Quindi, svaniremo nel h2
come un suggerimento al cliente.
Usiamo anche il metodo hover di jQuery per sbiadire le informazioni sul prodotto quando eseguiamo il mouseover e lo svaniscono quando eseguiamo il mouseout. Si noti che passiamo il nodo che stiamo passando sopra come contesto, quindi otteniamo solo il div del prodotto appropriato.
Ora aggiungiamo i gestori di eventi al #carrello
. Stiamo andando ad agire sul trascinare sopra
, DragEnter
, e far cadere
eventi:
$ ('# cart') .bind ('dragover', function (evt) evt.preventDefault ();) .bind ('dragenter', function (evt) evt.preventDefault ();) .bind ( 'drop', function (evt) );
Per far scattare l'evento di rilascio, è necessario annullare l'azione predefinita su trascinare sopra
evento; questo evento si attiva continuamente sull'obiettivo di rilascio quando un elemento trascinabile viene trascinato su di esso. Solo per IE, dobbiamo annullare l'azione predefinita su DragEnter
evento, che si verifica solo quando l'elemento trascinabile entra nella destinazione di rilascio. Le ragioni alla base dell'annullamento dell'azione predefinita sono alquanto nebbiose; ad essere onesti, non li capisco davvero. Ecco cosa dice Remy Sharp al riguardo:
Quello che sta dicendo al browser è che questo elemento è quello con cui vogliamo catturare l'evento di trascinamento, altrimenti il browser va avanti fa la normale azione di trascinamento. Quindi, cancellando l'evento, dice al browser che questo è l'elemento che dovrebbe iniziare a muoversi.
Dovrei notare che jQuery ci sta aiutando un po 'qui; normalmente, dovremmo anche restituisce falso
lo fa funzionare in IE; tuttavia, jQuery è stato risolto preventDefault
lo fa per noi.
Ora il far cadere
evento; anche questo evento viene sparato sull'obiettivo di rilascio, che è div # spesa
nel nostro caso. Prima di esaminare la funzione, parliamo di cosa dovrebbe fare questa funzione:
Ecco la prima parte:
var id = evt.dataTransfer.getData ('text'), item = $ ('#' + id), cartList = $ ("# cart ul"), total = $ ("# span totale"), price = $ ('p: eq (1) span', item) .text (), prevCartItem = null, notInCart = (function () var lis = $ ('li', cartList), len = lis.length, i; for (i = 0; i < len; i++ ) var temp = $(lis[i]); if (temp.data("id") === id) prevCartItem = temp; return false; return true; ()), quantLeftEl, quantBoughtEl, quantLeft;
Lo so; sono molte variabili, ma le useremo tutte. Andiamo su di loro; in primo luogo, otteniamo i dati di testo che abbiamo trasferito con l'evento; abbiamo trasferito l'id in questo modo perché non c'è nulla nell'oggetto evento che ci dica quale elemento è stato rilasciato sul nostro target; otterremo l'id e quindi lo useremo per trovare l'elemento che è stato rilasciato. Successivamente, otteniamo la lista dei carrelli e l'intervallo totale dei prezzi. Quindi, otterremo il prezzo del singolo oggetto; sappiamo che è lo span all'interno del secondo paragrafo dell'articolo, quindi possiamo usare l'elemento come parametro di contesto. Imposteremo prevCartItem
per nullare per ora, ma lo useremo per vedere se l'oggetto trascinato nel carrello è già lì. Il valore di notInCart
è una funzione anonima autoinvitante; passerà su ogni voce dell'elenco nella lista delle cartoline (di nuovo, stiamo usando il parametro di contesto) e controlleremo per vedere se la proprietà dei dati id
è uguale alla variabile id
. Per capire questo, devi sapere che quando aggiungiamo articoli al carrello, useremo il jQuery dati
metodo per impostare l'ID prodotto negozio con l'articolo. In questa funzione, stiamo verificando la presenza di una voce di elenco con i dati corretti; se ne troviamo uno, l'articolo è già nel carrello e così abbiamo impostato notInCart
a falso; se non è nel carrello, imposteremo la variabile su true. Finalmente, useremo quantLeftEl
, quantBoughtEl
, e quantLeft
quando si aggiornano le quantità.
Ora, per qualche azione:
$ ( "H2") fadeOut ( 'veloce.'); if (notInCart) prevCartItem = $ ('', text: $ (' p: first ', item) .text (), data: id: id). prepend ($ ('', ' class ':' quantity ', text:' 0 ')). prepend ($ ('', ' classe ':' prezzo ', testo: prezzo)). appendTo (listaCart);
Per prima cosa, svaniremo il h2
richiesta. Quindi, se l'articolo non è nel carrello, lo aggiungeremo al carrello. Per fare ciò, creeremo un elemento della lista; quindi, possiamo passare un oggetto letterale come secondo parametro per impostare le proprietà della nostra nuova voce di elenco. Imposteremo il testo sul nome del prodotto; che proviene dal primo paragrafo dell'articolo prodotto. Quindi, impostiamo i dati di cui abbiamo parlato sopra.
Successivamente, aggiungiamo un intervallo a questo elemento della lista; gli daremo una classe di "quantità" (non dimenticare di mettere la classe tra virgolette, poiché è una parola riservata) e impostare il testo a zero; sì, so che dovrebbe essere uno, dal momento che hanno appena messo l'oggetto nel carrello, ma lo incrementeremo più tardi ... e vedrai perché.
Anticiperemo un'altra spanna alla voce della lista, questa volta per il prezzo. Faremo galleggiare il prezzo a destra, quindi sembrerebbe logico aggiungere essa; ma ciò causerebbe un bug float in IE; lo span flutterebbe perfettamente a destra e sotto l'elemento della lista.
Infine, aggiungeremo l'elemento della lista all'elenco dei carrelli della spesa.
L'ultima parte di questa funzione verrà eseguita indipendentemente dal fatto che l'articolo sia già nel carrello o meno:
quantLeftEl = $ ('p: last span', item); quantLeft = parseInt (quantLeftEl.text (), 10) - 1; quantLeftEl.text (quantLeft); quantBoughtEl = $ ('. quantity', prevCartItem); quantBoughtEl.text (parseInt (quantBoughtEl.text (), 10) + 1); if (quantLeft === 0) item.fadeOut ('fast'). remove (); total.text ((parseFloat (total.text (), 10) + parseFloat (price.split ('$') [1])). toFixed (2)); evt.stopPropagation (); restituisce falso;
Innanzitutto otterremo la quantità dall'articolo del prodotto; questa è la quantità rimasta quando il cliente ha trascinato l'articolo sul carrello; otterremo quindi la quantità che è veramente rimasta; ma questa è una stringa, quindi usiamo la funzione nativa parseInt
per convertirlo in un numero (utilizzare 10 come radix per assicurare che si ottiene un numero decimale) e sottrarre uno da esso. Quindi ripristiniamo la quantità, usando jQuery testo
metodo.
Successivamente, otteniamo la quantità che l'utente ha acquistato; questo è l'elemento con una classe di "quantità"; noi usiamo il prevCartItem
come il contesto; questo funziona perché se l'articolo fosse già nel carrello, prevCartItem
era ambientato in quella funzione anonima; se non era nel carrello, lo impostiamo quando abbiamo creato la voce del carrello. Possiamo quindi impostare il valore del testo ottenendo il valore corrente, convertendolo in un numero e aggiungendone uno.
Cosa succede quando la quantità rimanente raggiunge zero? Se è zero, elimineremo l'elemento e lo rimuoverò.
Infine, dobbiamo aggiornare il prezzo totale. Abbiamo l'intervallo totale, quindi possiamo semplicemente resettare il testo; quello che stiamo facendo è ottenere il testo corrente, convertendolo in un numero (questa volta lo stiamo usando parseFloat
per mantenere i centesimi), separando il simbolo del dollaro dal prezzo e convertendolo in un numero e aggiungendo a due valori. Finalmente, useremo toFixed
per essere sicuri di mostrare sempre il valore dei centesimi corretto.
Infine, non vogliamo il far cadere
rilasciare evento a bolla, quindi interromperemo la sua propagazione e restituiremo false;
Bel lavoro, abbiamo finito; ecco una carrellata del nostro carrello in azione:
Se vuoi vedere cosa fanno gli altri eventi drag and drop, aggiungi questo allo script:
$ ('# carrello'). bind ('dragleave', function (evt) console.log ('dragleave');); $ ('. item') .bind ('dragend', function (evt) console.log ('dragend');) .bind ('dragstart', function (evt) console.log ('dragstart') ;) .bind ('drag', function (evt) console.log ('trascina'););
Sebbene il drag-and-drop nativo di HTML5 non sia ancora completamente pronto per la prima serata (Opera non lo supporta), è decisamente eccitante vedere dove vanno le cose!