Webbteknik 2

Laboration 6B

Drag and Drop - Minsta möjliga ansträngning

Nu när vi bekantat oss med de olika händelserna som ingår i drag and drop skall vi titta på vad vi faktiskt behöver göra för att skapa något användbart.

0 - Förberedelser

  1. Fortsätt jobba i samma folder som förra labben, lab-6.
  2. Skapa en b.js och länka in den i index.html genom att ersätta a.js i script-taggen.
  3. Överst i scriptfilen, skapa en konstant messages som innehåller elementet med id messages.

1 - Gör element dragbara

Börja med att göra elementen dragbara. Detta görs genom att sätta egenskapen draggable till true på varje element som ska kunna dras. Vi gjorde detta i förra labben, så det borde vara snabbt gjort att göra det igen.

Du behöver:

  • Loopa igenom alla element med klassen drag-item.
  • Sätta egenskapen draggable till true på varje sådan element.
Förslag på lösning
const draggables = document.querySelectorAll('.drag-item');

for (const draggable of draggables) {
  draggable.draggable = true;
}

Testa Nu bör du kunna dra och släppa elementen, men ännu händer såklart ingenting när vi gör det.

2 - Tillåt släpp i drop-zoner

Som du nog minns från förra labben behöver vi uttryckligen tillåta att man kan släppa elementen i drop-zoner.

Du behöver:

  • Loopa igenom alla element med klassen drop-zone.
  • Lägga till en eventlyssnare för dragover på varje sådan element.
  • I lyssnaren, anropa e.preventDefault(). Detta är nödvändigt för att tillåta drop (standardbeteendet är att inte tillåta drop).
Förslag på lösning
const dropZones = document.querySelectorAll('.drop-zone');

for (const zone of dropZones) {
  zone.addEventListener('dragover', function(event) {
    event.preventDefault();
  });
}

Testa Nu bör du kunna dra och släppa elementen. Men fortfarande händer inget när vi gör det.

3 - Hantera släppet

Slutligen behöver vi hantera vad som händer när användaren släpper elementet. Det görs med drop-eventet.

  1. Lägg till en eventlyssnare för drop på alla drop-zones (i samma loop som ovan eller en ny).
  2. I lyssnaren, sätt textContent på drop-zonen till texten “Släpp mottaget!”.

Förslag på lösning Loopen nedan är samma som ovan, men en händelsehanterare för drop är tillagd.

function onDrop(event) {
    event.preventDefault(); 
    event.target.textContent = "Släpp mottaget!";
}

for (const zone of dropZones) {
  zone.addEventListener('dragover', function(event) {
    event.preventDefault();
  });
  
  zone.addEventListener('drop', onDrop);
}

Testa Nu bör du kunna dra och släppa elementen. Men funktionaliteten är fortfarande ganska begränsad, eftersom vi inte har någon information om elementet som dras när vi hanterar drop-händelsen.

4 - Information om elementet som dras

Ett enkelt sätt att få tillgång till elementet som dras är att använda e.target i dragstart-eventet och spara referensen till elementet i en global variabel. Då kan vi använda den variabeln i exempelvis drop-eventet för att läsa ut data från elementet som dragits (och släppts).

Du behöver:

  • Lägga till en global variabel let draggedElement = null;.
  • Som reaktion på dragstart-eventet, sätta draggedElement till elementet som drog igång eventet (e.target).
  • Som reaktion på dragend-eventet, sätta draggedElement till null för att indikera att ingenting dras längre.
  • I onDrop, byta ut “Släpp mottaget!” mot värdet i draggedElement.textContent.
Förslag på lösning
let draggedElement = null;

for (const draggable of draggables) {
  draggable.draggable = true;
  draggable.addEventListener('dragstart', function(event) {
    draggedElement = event.target;
  });

  draggable.addEventListener('dragend', function() {
    draggedElement = null;
  });
}

Den nya onDrop-funktionen:

function onDrop(event) {
    event.preventDefault(); 
    event.target.textContent = draggedElement.textContent;
}

Det finns flera andra sätt kommuncera data mellan det dragna elementet och dropzonen, men detta är en enkel lösning som räcker gott just nu.