0
votes

I'm creating a simple picture puzzle game in JavaScript and am trying to implement the HTML5 Drag and Drop API. If I add an ondragstart, ondragover, or ondrop event to an element (i.e. as an attribute), it works.

However, because there are quite a few different elements in the same category I need to add event listeners to (which will only increase if I try to make a puzzle with more pieces), I'm using addEventListener to add the events. However, if I do this, it doesn't work. I've tested in Chrome and Firefox. For the record, I would really like to see if I can get this working with the HTML5 Drag and Drop API rather than with jQuery.

Here's the relevant JavaScript:

var piecesOnPage = document.querySelectorAll("#pieces img");
var puzzleSlots = document.getElementsByTagName("td");

function enableDrop(ev) {
    ev.preventDefault();
}

function dragPiece(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}

function dropPiece(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
}

function createEventListeners() {
    if (piecesOnPage[0].addEventListener) {
       for (i = 0; i < piecesOnPage.length; i++) {
        piecesOnPage[i].addEventListener("dragStart", dragPiece, false);
      }
    } else if (piecesOnPage[0].attachEvent) {
        for (i = 0; i < piecesOnPage.length; i++) {
        piecesOnPage[i].attachEvent("onDragStart", dragPiece);
       }
    }

   if (puzzleSlots[0].addEventListener) {
       for (i = 0; i < puzzleSlots.length; i++) {
        puzzleSlots[i].addEventListener("drop", dropPiece, false);
   }
    } else if (puzzleSlots[0].attachEvent) {
       for (i = 0; i < puzzleSlots.length; i++) {
       puzzleSlots[i].attachEvent("onDrop", dropPiece);
      }
    }

    if (puzzleSlots[0].addEventListener) {
       for (i = 0; i < puzzleSlots.length; i++) {
        puzzleSlots[i].addEventListener("dragOver", enableDrop, false);
       }
    } else if (puzzleSlots[0].attachEvent) {
        for (i = 0; i < puzzleSlots.length; i++) {
        puzzleSlots[i].attachEvent("onDragOver", enableDrop);
       }
    }
}

if (window.addEventListener) {
   window.addEventListener("load", createEventListeners, false);
} else if (window.attachEvent) {
   window.attachEvent("onload", createEventListeners);
}

Here's the accompanying HTML. Note that, in order to demonstrate the fact that normal events work but addEventListener doesn't, I've added a normal event to the first puzzle piece and the first puzzle slot. Those work fine, but the rest don't.

<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
<head>
<title>Puzzles</title>
<style>
    table {
    border:1px #000000 solid;
    border-collapse:collapse;
    float:right;
    margin:10px;
}

td {
    padding:0;
    line-height:0;
    height:96px;
    width:157px;
}
</style>
</head>

<body>
    <table class="puzzleboard">
        <thead></thead>
        <tbody>
            <tr><td id="space1" ondrop="dropPiece(event)" ondragover="enableDrop(event)"></td><td id="space2"></td><td id="space3"></td></tr>
            <tr><td id="space4"></td><td id="space5"></td><td id="space6"></td></tr>
            <tr><td id="space7"></td><td id="space8"></td><td id="space9"></td></tr>
        </tbody>
    </table>
    <div id="pieces">
        <img id="img1" draggable="true" ondragstart="dragPiece(event)" src="2-2.jpeg"><img id="img2" draggable="true" src="1-2.jpeg"><img id="img3" draggable="true" src="2-1.jpeg"><br>
        <img id="img4" draggable="true" src="0-2.jpeg"><img id="img5" draggable="true" src="1-0.jpeg"><img id="img6" draggable="true" src="0-1.jpeg"><br>
        <img id="img7" draggable="true" src="1-1.jpeg"><img id="img8" draggable="true" src="2-0.jpeg"><img id="img9" draggable="true" src="0-0.jpeg"><br>
    </div>
<script src="final-so.js"></script>
</body>
</html>

First Stack Overflow question ever, hope I didn't do anything TOO stupid ;)

2
"For the record, I would really like to see if I can get this working with the HTML5 Drag and Drop API rather than with jQuery." You do realize you don't need jquery for this....Phix
I know, that's actually kind of the point. It's just that whenever drag-and-drop comes up it seems that jQuery is mentioned, and I would rather just use HTML & plain JavaScript. Sorry that I didn't make that clear! '^^TJD

2 Answers

1
votes

Add some height and width to the img element .

<img id="img1" draggable="true" ondragstart="dragPiece(event)" src="2-2.jpeg" height="100" width="100">

this solved the issue

1
votes

I know it's been some years, but I'm working with draggable now too and there's little info on this post about using it alongside addEventListener so maybe it can help somebody.

Be aware that the drag events have different names in the addEventListener API and in HTML attribute (this is true for other events too). In your case:

piecesOnPage[i].addEventListener("dragStart", dragPiece, false);

Should be

piecesOnPage[i].addEventListener("dragstart", dragPiece, false);

Same for dragOver; it should be dragover

Documentation: https://developer.mozilla.org/en-US/docs/Web/API/Document/dragstart_event