Een van de nieuwe functies in HTML5 is native slepen en neerzetten. Verrassend genoeg heeft Internet Explorer sinds versie 5.5 ondersteuning voor native slepen en neerzetten; in feite is de HTML5-implementatie gebaseerd op IE's ondersteuning. In de tutorial van vandaag zullen we bekijken hoe native slepen en neerzetten kunnen worden geïmplementeerd om een eenvoudige winkelwageninterface te maken.
Dit is wat we gaan bouwen: het is een standaard winkelwagentje met een productpaneel en een wagenpaneel. Om een product te "kopen", kunt u het van het paneel naar het winkelwagentje slepen; we houden de hoeveelheden bij en verwijderen items uit het productpaneel wanneer ze niet op voorraad zijn.
Merk op dat we hier eigenlijk geen winkelwagentje bouwen; we zullen vandaag niet met enige goedheid aan de server werken. Dit is slechts het front-end; het punt is HTML5 slepen en neerzetten.
Natuurlijk beginnen we met de HTML; hier is onze schaal:
Drag en drop winkelwagentje
Best simpel: we linken naar een stylesheet en jQuery; we gebruiken jQuery alleen voor eenvoudige eventafhandeling en DOM-manipulatie; het slepen en neerzetten zal native zijn. We zijn hier echter tegen een muur, omdat HTML5 slepen en neerzetten een paar eigenschappen toevoegt aan het gebeurtenisobject. JQuery maakt geen gebruik van het standaardgebeurtenisobject; het maakt zijn eigen om problemen met gebeurtenisobjecten gelijk te maken. Daarom krijgen we niet de speciale eigenschappen met het gebeurtenisobject jQuery. Maar maak je geen zorgen; er is een plugin voor; we trekken de Native Drag and Drop in om alles te laten werken. Ten slotte nemen we ons script op: dragdrop.js
.
Nu zijn we klaar om toe te voegen aan onze productlijst; voor productafbeeldingen, gebruik ik pictogrammen van het Apple Icon Superpack, gemaakt door SvenVath. (Ik heb de pictogrammen hernoemd met eenvoudigere namen en de grootte ervan veranderd naar 180 px.)
Toevoegen ul # producten
als het eerste kind in het lichaam. Zodra je dat hebt gedaan, zullen we het eerste lijstitem bekijken:
iMac
Prijs: $ 1199.00
Aantal stuks: 10
We hebben een lijstitem met een anker erin; merk op dat elk ankeritem een klasse van heeft item
(belangrijk als we bij de CSS komen) en een aangepaste id (belangrijk als we bij de JavaScript komen). Dan heeft het anker ook de draggable = "true"
attribuut; dit zou alles moeten zijn wat we nodig hebben om het element versleepbaar te maken (we zullen binnenkort een paar waarschuwingen tegenkomen). We gebruiken hier een ankertag, zodat u iets voor browsers kunt doen zonder de oorspronkelijke ondersteuning voor slepen en neerzetten (hoewel we dat hier niet doen). Dan hebben we de productafbeelding en een div met de productinformatie. En ja, het is noodzakelijk om de prijs en hoeveelheid in te pakken span
Dit zijn de rest van de lijstitems:
iPhone
Prijs: $ 199.00
Aantal stuks: 16
Apple TV
Prijs: $ 299.00
Aantal stuks: 9
Cinema Display
Prijs: $ 899.00
Aantal stuks: 4
Ipod Nano
Prijs: $ 149.00
Aantal stuks: 20
Macbook
Prijs: $ 1199.00
Aantal stuks: 13
Mac Mini
Prijs: $ 599.00
Aantal stuks: 18
Er is nog een laatste stukje HTML: het winkelwagentje:
Winkelwagen
Totaal: $0.00
Laat het hier vallen om toe te voegen aan je winkelwagen
En dat is onze HTML!
In het ideale geval is alles wat u moet doen om een element versleepbaar te maken, dat versleepbare kenmerk in te stellen op waar; er is echter meer aan de hand. Om dingen goed te laten werken, moet je een paar dingen in CSS instellen. Denk eerst eens aan dit: wat doet klikken en slepen met "normaal" (niet-versleutelbaar) element? Meestal selecteert het tekst. Vervolgens willen we zeker weten dat we het element slepen, en niet alleen de inhoud ervan. Om hiermee om te gaan, moet je de volgende CSS gebruiken:
[draggable = true] -moz-user-select: none; -webkit-user-select: geen; -webkit-gebruiker-drag: element;
Voor ons gemak stelt de native plug-in plug-in die we gebruiken deze eigenschappen in voor ons, zodat we ze kunnen weglaten als we dat willen. We zullen dit echter doen:
[draggable = true] cursor: verplaatsen;
Laten we beginnen met stileren:
html height: 100%; body background: #ececec; margin: 0; padding: 0; lettertype: 13px / 1,5 helvetica, arial, san-serif; hoogte: 100%; h1, h2 text-align: center; h2 positie: absoluut; onder: 20px; color: # fff; text-shadow: 0 0 10px rgba (0, 0, 0, 0.75); Geen weergeven; p marge: 0;
Omdat we geen volledige reset gebruiken, is dit onze pseudo-reset. Het moet allemaal behoorlijk vanzelfsprekend zijn. We stellen de hoogte in op 100% html
en lichaam
elementen omdat we willen #cart
om de volledige hoogte van het scherm te zijn; om dat te doen, moet voor elk ouderelement de hoogte op 100% worden ingesteld. Merk ook op dat we rgba gebruiken om de schaduwkleur in te stellen; als een browser dit niet ondersteunt, zal er geen schaduw zijn op de h2
. En we verbergen dit h2
door in te stellen Geen weergeven
. Herinner de h2
zegt "Drop hier om aan winkelwagen toe te voegen", dus we laten het vervagen wanneer het slepen begint en uitdoemen wanneer het slepen eindigt.
Verder gaan naar onze productenlijst ...
#products float: left; list-style: none; width: 65%; padding: 0; #products li display: inline;
Nogmaals, vrij voor de hand liggend. Het belangrijkste in dit fragment is dat de lijstitems inline worden weergegeven. Omdat we zullen instellen display: block; float: left
op de ankers zal IE de lijstitems een "traptreden" -effect geven; we kunnen deze bug omzeilen door in te stellen weergeven: inline
op het bovenliggende element van het anker.
Over de ankers gesproken, laten we ze daarna stylen.
.item display: block; float: left; width: 180px; Hoogte: 180px; margin: 10px; rand: 1px vast # 494949; text-align: center; text-decoration: none; kleur: # 000; overloop verborgen; .item img border: 0; marge: 10px auto; width: 160px; Hoogte: 160px; .item div background: rgb (0, 0, 0); achtergrond: rgba (0, 0, 0, 0,5); position: relative; bottom: 69px; color: # f3f3f3; opvulling: 5px 0; Geen weergeven;
Elk anker zal worden gestileerd als een doos van 180x180px; dit wordt gevuld met de productafbeelding. De productinformatie-div wordt boven de afbeelding op de onderkant van het vierkant geplaatst. Merk op dat we een achtergrondkleur moeten instellen en deze vervolgens moeten resetten voor moderne browsers, omdat IE RGBA niet ondersteunt. We gaan zitten Geen weergeven
op deze info-div zodat we het kunnen laten vervagen wanneer de 'klant' aan en uit zweeft, respectievelijk.
Het enige dat overblijft om stijl te maken, is het winkelwagentje; we zullen het hier bekijken, maar vergeet niet dat de lijstitems later door jQuery zullen worden ingevoegd, zodat je dit nog niet zult zien plaatsvinden.
#cart float: right; background-color: #ccc; width: 25%; opvulling: 0 5%; height: 100%; #cart ul opvulling: 0; #cart li list-style: none; border-bottom: 1px solid # 494949; padding: 5px; # winkelwagen. hoeveelheid font-weight: bold; padding-right: 10px; margin-right: 10px; border-right: 1px solid # 494949; weergave: inline-block; width: 15px; text-align: right; # winkelwagen. prijs float: right; #totaal float: right;
Elementen met de klassen aantal stuks
en prijs
bevindt zich in de dynamisch ingevoegde lijstitems.
Dat is het voor CSS; voordat we naar de ster van deze show gaan, laten we ons werk tot nu toe bekijken.
We hebben het in het JavaScript gehaald; volgens de de HTML5-arts:
HTML 5 DnD is gebaseerd op de originele implementatie van Microsoft die al beschikbaar was in Internet Explorer 5! Nu ondersteund in IE, Firefox 3.5 en Safari 4.
Hier is een lijst met de gebeurtenissen die aanbiedingen van HTML5 slepen en neerzetten:
We zullen dit niet allemaal gebruiken, maar we zullen zien hoe ze het meeste werken.
Eerst zullen we werken met onze producten:
$ ('. item'). bind ('dragstart', function (evt) evt.dataTransfer.setData ('text', this.id); $ ('h2'). fadeIn ('fast');) .hover (function () $ ('div', this) .fadeIn ();, function () $ ('div', this) .fadeOut (););
We beginnen met het pakken van alle items; dan binden we een funciton aan de dragstart
evenement; deze gebeurtenis wordt geactiveerd wanneer we de gebeurtenis beginnen te slepen. Het eerste dat we doen wanneer een object wordt gesleept, is een aantal gegevens; eigenlijk, als er geen gegevens zijn ingesteld, zal firefox het element niet laten slepen. Speciaal om gebeurtenissen te slepen, is een eigenschap object op het opgeroepen evenementobject data overdracht
; we gebruiken twee methoden van deze eigenschap: setData
en gegevens verkrijgen
. Hier gebruiken we de setData
methode, die twee parameters vergt: een gegevensformaat en de gegevens. We gebruiken het datatype 'tekst'. Vervolgens stellen we de gegevens in als het ID van het element dat de gebruiker sleept. Dan verdwijnen we in de h2
als een prompt naar de klant.
We gebruiken ook de jQuery hover-methode om de productinformatie te laten vervagen wanneer we de muisaanwijzer overnemen en uitfaden wanneer we de muis uit gaan. Merk op dat we het knooppunt waarover we zweven, doorgeven als context, dus we krijgen alleen de div van het juiste product.
Laten we nu eventhandlers toevoegen aan de #cart
. We gaan handelen op de overdragen
, dragenter
, en laten vallen
events:
$ ('# winkelwagen') .bind ('dragover', functie (evt) evt.preventDefault ();). bind ('dragenter', function (evt) evt.preventDefault ();). bind ( 'drop', functie (evt) );
Om de gebeurtenis drop-off te activeren, moeten we de standaardactie annuleren op de overdragen
evenement; deze gebeurtenis vuurt continu op het doel van de slag wanneer er een versleepbaar element overheen wordt gesleept. Alleen voor IE moeten we de standaardactie op de server annuleren dragenter
gebeurtenis, die alleen optreedt wanneer het versleepbare element het doel voor de neerzet ingaat. De redenen achter het annuleren van de standaardactie zijn enigszins mistig; om eerlijk te zijn, begrijp ik ze niet echt. Dit is wat Remy Sharp erover zegt:
Wat het de browser vertelt is dat dit element degene is waar we de sleepgebeurtenis tegen willen vangen, anders gaat de browser door met het doen van normale sleepactie. Dus door de gebeurtenis te annuleren, vertelt het de browser dat dit het element is dat moet beginnen met bewegen.
Ik moet er rekening mee houden dat jQuery ons hier een beetje helpt; normaal zouden we dat ook moeten doen return false
het laat het werken in IE; jQuery is echter gerepareerd voorkom standaard
doet dat voor ons.
Nu de laten vallen
evenement; deze gebeurtenis wordt ook afgevuurd op het doelwit van de dropping div # cart
in ons geval. Voordat we naar de functie kijken, laten we het hebben over wat deze functie zou moeten doen:
Dit is het eerste deel:
var id = evt.dataTransfer.getData ('tekst'), item = $ ('#' + id), cartList = $ ("# cart ul"), total = $ ("# total span"), price = $ ('p: eq (1) span', item) .text (), prevCartItem = null, notInCart = (function () var lis = $ ('li', cartList), len = lis.length, i; voor (i = 0; i < len; i++ ) var temp = $(lis[i]); if (temp.data("id") === id) prevCartItem = temp; return false; return true; ()), quantLeftEl, quantBoughtEl, quantLeft;
Ik weet; het zijn veel variabelen, maar we zullen ze allemaal gebruiken. Laten we erover gaan; eerst krijgen we de tekstgegevens die we met de gebeurtenis hebben overgedragen; we hebben de id zo overgedragen omdat er niets in het gebeurtenisobject staat om ons te vertellen welk element op ons doelwit is neergezet; we krijgen het ID en gebruiken het om het element te vinden dat is weggelaten. Vervolgens krijgen we de cartelijst en de totale prijsomvang. Vervolgens krijgen we de prijs van het afzonderlijke artikel; we weten dat dit de overspanning is binnen de tweede alinea van het item, zodat we het item kunnen gebruiken als de contextparameter. We zullen beginnen prevCartItem
om nu te annuleren, maar we zullen het gebruiken om te zien of het item dat in de winkelwagen wordt gesleept al aanwezig is. De waarde van notInCart
is een zichzelf aanroepende anonieme functie; het zal lus over elk lijstitem in de cartList (nogmaals, we gebruiken de contextparameter) en controleer om te zien of de eigenschap data ID kaart
is hetzelfde als de variabele ID kaart
. Om dit te begrijpen, moet u weten dat wanneer we lijstitems toevoegen aan het winkelwagentje, we jQuery gebruiken gegevens
methode om het winkelproduct-ID in te stellen voor het artikel. In deze functie controleren we op een lijstitem met de juiste gegevens; als we er een vinden, staat het item al in de winkelwagen, en dus zijn we klaar notInCart
tot onwaar; als dit niet in de winkelwagen staat, stellen we de variabele in op true. Eindelijk, we zullen gebruiken quantLeftEl
, quantBoughtEl
, en quantLeft
bij het updaten van hoeveelheden.
Nu, voor wat actie:
$ ( "H2") fade-out ( 'snel').; if (notInCart) prevCartItem = $ ('', text: $ (' p: first ', item) .text (), data: id: id). prepend ($ ('', ' class ':' quantity ', text:' 0 ')). prepend ($ ('', ' class ':' price ', text: price)). appendTo (cartList);
Ten eerste zullen we de h2
prompt. Als het artikel niet in de winkelwagen staat, voegen we het toe aan de winkelwagen. Om dit te doen, zullen we een lijstitem maken; dan kunnen we een object letterlijk doorgeven als de tweede parameter om eigenschappen van ons nieuwe lijstitem in te stellen. We zullen de tekst instellen op de productnaam; dat komt uit de eerste paragraaf in het artikel. Vervolgens stellen we de gegevens in waar we het eerder over hadden.
Vervolgens voegen we een bereik toe aan dit lijstitem; we geven het een klasse van 'kwantiteit' (vergeet niet om klasse tussen aanhalingstekens te plaatsen, omdat het een gereserveerd woord is) en de tekst op nul te zetten; ja, ik weet dat het er een zou moeten zijn, omdat ze het artikel net in het winkelwagentje hebben gestopt, maar we zullen dat later verhogen ... en je zult zien waarom.
We zullen een andere reeks toevoegen aan het lijstitem, deze keer voor de prijs. We zullen de prijs naar rechts duwen, dus het lijkt logisch toevoegen het; maar dat zou een float-bug veroorzaken in IE; de overspanning zou dan gelijk en onder het lijstitem zweven.
Ten slotte voegen we het lijstitem toe aan de winkelwagenlijst.
Het laatste deel van deze functie wordt uitgevoerd ongeacht of het item al in de winkelwagen zit of niet:
quantLeftEl = $ ('p: laatste 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 (); return false;
Eerst krijgen we de hoeveelheid van het productitem; dit is de hoeveelheid die overblijft wanneer de klant het artikel naar de winkelwagen heeft gesleept; we zullen dan de hoeveelheid krijgen die echt overblijft; maar dat is een string, dus we gebruiken de native functie parseInt
om het naar een getal te converteren (gebruik 10 als de radix om te zorgen dat we een decimaal getal krijgen) en trek er een ervan af. Vervolgens wordt de hoeveelheid opnieuw ingesteld met behulp van jQuery's tekst
methode.
Vervolgens krijgen we de hoeveelheid die de gebruiker heeft gekocht; dit is het element met een klasse van 'kwantiteit'; wij gebruiken de prevCartItem
als de context; dit werkt omdat het artikel al in de winkelwagen zat, prevCartItem
was ingesteld in die anonieme functie; als het niet in de winkelwagen was, hebben we dit ingesteld toen we het winkelwagentje maakten. We kunnen dan de tekstwaarde instellen door de huidige waarde te krijgen, naar een getal te converteren en er een toe te voegen.
Wat gebeurt er als de resterende hoeveelheid nul raakt? Als het nul is, vervagen we het item en verwijderen het.
Ten slotte moeten we de totale prijs bijwerken. We hebben de totale tijdsspanne, dus we kunnen de tekst gewoon opnieuw instellen; wat we doen, is de huidige tekst ophalen, deze naar een getal converteren (deze keer gebruiken we dit parseFloat
om de cent te houden), het dollarteken van de prijs te splitsen en dat naar een getal te converteren en toe te voegen aan twee waarden. Eindelijk, we zullen gebruiken toFixed
om ervoor te zorgen dat we altijd de juiste centwaarde weergeven.
Ten slotte willen we het laten vallen
drop event om te bubbelen, dus we stoppen de propagatie ervan en retourneren false;
Goed gedaan, we zijn klaar; hier is een foto van onze winkelwagen in actie:
Als je wilt weten wat de andere slepen en neerzetten-events doen, voeg dit dan toe aan het script:
$ ('# cart'). 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 ('drag'););
Hoewel native HTML5 slepen en neerzetten misschien nog niet helemaal klaar is voor prime time (Opera ondersteunt het niet), is het echt spannend om te zien waar dingen naartoe gaan!