JSFiddle - React, Tailwind, and code Playground
HTML
<div id="container">
<div id="dropzone1" class="dropzone" dropzone="move">
<div id="draggable1" class="draggable" draggable="true">1</div>
<div id="draggable2" class="draggable" draggable="true">2</div>
<div id="draggable3" class="draggable" draggable="true">3</div>
<div id="draggable4" class="draggable" draggable="true">4</div>
</div>
<div id="dropzone2" class="dropzone" dropzone="move">
</div>
</div>
<div class="toolBar">
<label for="monitorEventsToggle">
<input type="checkbox" id="monitorEventsToggle"/>
<u>M</u>onitor events
</label>
<input type="button" value="Clear Log" onclick="window.eventLog.innerText = ''"/>
</div>
<pre id="eventLog"></pre>
CSS
html, body {
margin: 0;
padding: 0;
height: 100%;
}
body {
margin-top: 320px;
}
.toolBar {
position: fixed;
top: 300px;
left: 0;
right: 0;
user-select: none;
background: #EEE;
}
.toolBar>* {
margin: 8px 12px;
}
#container {
background: #DDD;
height: 300px;
position: fixed;
top: 0;
left: 0;
right: 0;
}
.dropzone {
display: inline-block;
margin: 20px;
padding: 20px;
border: 2px dashed #050;
background: #EFE;
width: 200px;
height: 200px;
float: left;
}
.draggable {
display: inline-block;
margin: 4px;
border: 1px solid #AAF;
background: #DEF;
width: 50px;
height: 50px;
cursor: grab;
text-align: center;
line-height: 50px;
}
.draggable:active {
cursor: grabbing;
}
JavaScript
function getStandardEventNames(element) {
const eventNames = []
for (const prop in element) {
if (prop.startsWith("on")) {
const eventName = prop.slice(2)
try {
new Event(eventName)
eventNames.push(eventName)
} catch {}
}
}
return eventNames.sort()
}
function monitorEvents(cssSelector, eventNames) {
for (const element of document.querySelectorAll(cssSelector)) {
for (const eventName of eventNames) {
element.addEventListener(eventName, function (event) {
if (window.monitorEventsToggle.checked) {
event.stopPropagation();
window.eventLog.append(
`${
event.target.id
? `#${event.target.id}`
: event.target.tagName.toLowerCase()
} ${event.type}\n`
)
}
})
}
}
}
function allowDragging(cssSelector) {
for (const element of document.querySelectorAll(cssSelector)) {
element.ondragstart = function (event) {
event.dataTransfer.effectAllowed = "move"
event.dataTransfer.clearData()
event.dataTransfer.setData("text", event.target.id)
}
}
}
function allowDropping(cssSelector) {
for (const element of document.querySelectorAll(cssSelector)) {
element.ondragover = (event) => event.preventDefault()
element.ondrop = function (event) {
event.preventDefault()
event.target.appendChild(
document.getElementById(event.dataTransfer.getData("text")),
)
}
}
}
function groupConsoleMessage(duration) {
console.group()
setInterval(function () {
console.groupEnd()
console.group()
}, duration)
}
allowDragging(".draggable")
allowDropping(".dropzone")
const events = getStandardEventNames(document.body)
monitorEvents("#container, .dropzone, .draggable", events)
window.onkeypress = event => event.key === 'm' && (window.monitorEventsToggle.checked = !window.monitorEventsToggle.checked);