ibnhamza
ibnhamza

Reputation: 871

Drag Events Only firing once

I'm working on a kind of puzzle game with HTML5 drag and drop api. I build a grid of 3 rows with 4 col per row giving me twelve squares. All but one of the squares contains some numbers from 1 to 11. The empty square is meant to be the dropzone i.e where any square can be dragged into.

When an element is dragged the dataTransfer.setData is set to the id of the element being dragged while ondrop event gets the data using dataTransfer.getData() result of which is used to query the dom for the element being dragged, then cloned after which the dropzone is now replaced with the cloned node. The source from which the dragged element is coming is also replaced with a dropzone.

var squares = document.querySelectorAll(".item");
var dropzone = document.querySelector(".col-lg-3.dropzone");

function startDrag(e){
    e.dataTransfer.setData("text", e.target.id);
    console.log(e.target)

}

function overDrag(e){
    e.preventDefault();
    e.target.classList.toggle("dropzone-active");

}

function leaveDrag(e){
    e.preventDefault();
    e.target.classList.toggle("dropzone-active");
}

function dropItem(e){
    e.preventDefault();
    var data = e.dataTransfer.getData("text");
    var draggedElem = document.getElementById(data)
    var clone = draggedElem.cloneNode(true);
    var emptyzone = dropzone.cloneNode(false);
    emptyzone.className = "col-lg-3 dropzone";
    draggedElem.parentNode.replaceChild(emptyzone,draggedElem);

    clone.id = data;
    e.target.parentNode.replaceChild(clone, e.target);
}


for(var i=0; i<squares.length; i++){
    squares[i].addEventListener("dragstart", startDrag, false);
}
dropzone.addEventListener("dragover", overDrag, false);
dropzone.addEventListener("dragleave", leaveDrag, false);
dropzone.addEventListener("drop", dropItem, false);
	#gameZone{
		width:800px;
		height:500px;
		background-color: rgba(0,0,0,.5);
		margin: 0 auto;
		padding:15px;
		position:relative;
	}
	.item,
	.dropzone{
		background-color:red;
		margin-right:10px;
		margin-bottom:15px;
		width:100px;
		height:100px;
		font-size: 2em;
		color:#fff;
		text-align:center;
	}
	.drag-active{
		position:absolute;
		z-index: 10;
	}
	.dropzone-active{
		border:dashed 3px white;
	}

	.dropzone{
		background-color:rgba(255,255,255,.6);
	}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<section id="gameZone">
	<div class="row">
		<div class="col-lg-3 item" id="one" draggable="true">1</div>
		<div class="col-lg-3 item" id="three" draggable="true">3</div>
		<div class="col-lg-3 item" id="two" draggable="true">2</div>
		<div class="col-lg-3 item" id="four" draggable="true">4</div>
	</div>
	<div class="row">
		<div class="col-lg-3 dropzone"></div>
		<div class="col-lg-3 item" id="five" draggable="true">5</div>
		<div class="col-lg-3 item" id="six" draggable="true">6</div>
		<div class="col-lg-3 item" id="nine" draggable="true">9</div>
	</div>
	<div class="row">
		<div class="col-lg-3 item" id="seven" draggable="true">7</div>
		<div class="col-lg-3 item" id="eight" draggable="true">8</div>
		<div class="col-lg-3 item"id="eleven"  draggable="true">11</div>
		<div class="col-lg-3 item" id="ten" draggable="true">10</div>
	</div>
</section>

The problem now is that the first drag and drop action is successful, however, trying to drag a new element in the new dropzone doesn't work, it just doesn't recognize the ondragenter, ondragleave, ondragover and the drop events anymore.

Upvotes: 1

Views: 2440

Answers (1)

guest271314
guest271314

Reputation: 1

You can create a function to set dropzone variable, attach dragover, dragleave, drop events to current dropzone element. Within drop event listener call function passing data to attach dragstart event to element currently having id data.

var squares = document.querySelectorAll(".item");
var dropzone;

//= document.querySelector(".col-lg-3.dropzone");

function startDrag(e) {
  e.dataTransfer.setData("text", e.target.id);
}

function overDrag(e) {
  e.preventDefault();
  e.target.classList.toggle("dropzone-active");
}

function leaveDrag(e) {
  e.preventDefault();
  e.target.classList.toggle("dropzone-active");
}

function dropItem(e) {
  e.preventDefault();
  var data = e.dataTransfer.getData("text");
  var draggedElem = document.getElementById(data)
  var clone = draggedElem.cloneNode(true);
  var emptyzone = dropzone.cloneNode(false);
  emptyzone.className = "col-lg-3 dropzone";
  draggedElem.parentNode.replaceChild(emptyzone, draggedElem);

  clone.id = data;
  e.target.parentNode.replaceChild(clone, e.target);
  setResetDND(data);
}


for (var i = 0; i < squares.length; i++) {
  squares[i].addEventListener("dragstart", startDrag, false);
}

function setResetDND(id) {
  dropzone = document.querySelector(".col-lg-3.dropzone");

  dropzone.addEventListener("dragover", overDrag, false);
  dropzone.addEventListener("dragleave", leaveDrag, false);
  dropzone.addEventListener("drop", dropItem, false);
  if (id) {
    document.getElementById(id)
    .addEventListener("dragstart", startDrag)
  }
}

setResetDND();
#gameZone {
  width: 800px;
  height: 500px;
  background-color: rgba(0, 0, 0, .5);
  margin: 0 auto;
  padding: 15px;
  position: relative;
}
.item,
.dropzone {
  background-color: red;
  margin-right: 10px;
  margin-bottom: 15px;
  width: 100px;
  height: 100px;
  font-size: 2em;
  color: #fff;
  text-align: center;
}
.drag-active {
  position: absolute;
  z-index: 10;
}
.dropzone-active {
  border: dashed 3px white;
}
.dropzone {
  background-color: rgba(255, 255, 255, .6);
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<section id="gameZone">
  <div class="row">
    <div class="col-lg-3 item" id="one" draggable="true">1</div>
    <div class="col-lg-3 item" id="three" draggable="true">3</div>
    <div class="col-lg-3 item" id="two" draggable="true">2</div>
    <div class="col-lg-3 item" id="four" draggable="true">4</div>
  </div>
  <div class="row">
    <div class="col-lg-3 dropzone"></div>
    <div class="col-lg-3 item" id="five" draggable="true">5</div>
    <div class="col-lg-3 item" id="six" draggable="true">6</div>
    <div class="col-lg-3 item" id="nine" draggable="true">9</div>
  </div>
  <div class="row">
    <div class="col-lg-3 item" id="seven" draggable="true">7</div>
    <div class="col-lg-3 item" id="eight" draggable="true">8</div>
    <div class="col-lg-3 item" id="eleven" draggable="true">11</div>
    <div class="col-lg-3 item" id="ten" draggable="true">10</div>
  </div>
</section>

Upvotes: 1

Related Questions