JavaScript — Introduktion genom exempel

13.2 Drag items

Detta kapitel tar upp Pointer events, för att hantera drag-and-drop och andra pekaroperationer. I detta exempel går vi dock endast igenom hantering av drag items (de element som dras). Sedan fortsätter vi med hantering av drop zones (de element man kan släppa på) i nästa exempel. Genom att använda pointer events, kan vi skapa en kod som fungerar både på en dator med mus och på en pekskärm.

Vi tar upp två olika sätt att dra ett element. I det ena fallet skapas en klon av elementet och man drar sedan klonen. I det andra fallet dras originalet.

Del a och b — 38 min.

Del c och d — 19 min.

Sammanfattning

För hantering av mus finns Mouse Events och för hantering av pekskärm finns Touch Events. Pointer Events kombinerar dessa båda, så att vi inte behöver dubblera händelselyssnare eller kod för olika typer av enheter, utan istället används endast de händelser som finns i Pointer Events. Det finns flera olika händelser definierade, men i detta och kommande exempel är det de fyra följande som används:

Kodens struktur och hantering av händelselyssnare

I init-funktionen lägger vi endast på händelselyssnare för pointerdown. Detta läggs på alla element som ska kunna dras. Den funktion som då anropas kallar vi pointerStart.

I pointerStart förbereder vi för pekaroperationen och lägger på övriga händelselyssnare. Dessa läggs oftast på document. Vid pointermove anropar vi en funktion kallad pointerMove och vid både pointerup och pointercancel anropar vi funktionen pointerEnd.

Funktionerna pointerMove och pointerEnd läggs inuti funktionen pointerStart. Därmed kan de lokala variabler som införs i pointerStart användas i alla tre funktionerna. Samtidigt ger denna struktur en gruppering och inneslutning av den kod som hanterar hela pekaroperationen.

I pointerMove känner man av pekarens position och flyttar med elementet till den positionen. Det är det övre vänstra hörnet som positioneras, så för att pekaren ska ligga kvar inom elementet på samma plats som då den trycktes ner, får man kompensera för pekarens startposition, som tas fram i pointerStart.

I pointerEnd städar man upp genom att ta bort händelselyssnarna som lades på i pointerStart. Man kan också behöva göra en del annan "uppstädning", beroende på vad som gjorts i pointerStart.

Event-objektet

Event-objektet för pekaren ärver egenskaper från Mouse Event, bl.a. olika par av X- och Y-koordinater, men det innehåller också en del egenskaper som endast är specifika för Pointer Events, t.ex. isPrimary. Denna egenskap är true för den första pekaren som trycks ner och false för övriga. I exemplet används den för att se till att vi på en pekskärm endast bryr oss om den första pekaren i den operation som hanteras här.

För att avläsa pekarens position används i detta exempel pageX och pageY, som är pekarens position inom hela dokumentet.

Koordinater för element

För element kan vi använda offsetLeft och offsetTop, för att avläsa positionen för dess övre vänstra hörn. Om elementet ligger inom ett annat element som har en annan poisition än static, är offset-värdena avstånd till det omgivande elementets vänster- och överkant. I annat fall är de avstånd till dokumentets vänster- och överkant. De avlästa värdena är alltid i pixel och är numeriska värden. De kan endast avläsas, så man kan inte tilldela dem nya värden.

Man kan också använda en funktion kallad getBoundingClientRect() för att få fram elementets placering inom webbläsarens fönster. Även dessa är numeriska värden i enheten pixel och de kan endast avläsas.

För att ge ett element en ny position måste man använda CSS-egenskaperna left och top. Det är enda möjligheten som finns för att lägga in nya värden för elementets placering.

CSS-egenskaperna user-select och touch-action

Båda dessa egenskaper kan sättas till none eller auto, där auto är default-värdet. För de element man ska kunna dra brukar man lägga in none på båda. Man tar med user-select:none, för att det inte ska gå att markera innehållet i ett elementen som ska dras. Det kan annars se konstigt ut om man t.ex. råkar trycka ner pekaren utanför elementet och drar över det. Man tar med touch-action:none, för att förhindra en del standardoperationer på en pekskärm. Normalt scrollar man webbsidan då man på en pekskärm trycker ner fingret och drar, men ska man dra ett element på sidan, vill man ju inte att dokumentet ska scrollas.

Händelsen touchstart och preventDefault()

För att förhindra att det poppar upp en markering eller meny för att dela eller spara, då man på en pekskärm trycker ner och håller pekaren nedtryckt en liten stund på en text eller bild, tar man också med en händelselyssnare för touchstart i de element som ska kunna dras. I händelselyssnarens funktion utför man e.preventDefault().

Egna övningar

Övning på detta ingår i övningen i nästa exempel.