When iam dropping my div with an image inside i get nothing and after i am trying to get it ID i get null of course. But how can i get info from a div with image and append row with it? Code here or check codepen: https://codepen.io/13reathcode/pen/NWBmZpb
'use strict';
let queuedImagesArray = [],
queuedForm = document.querySelector('#queued-form'),
queuedDiv = document.querySelector('.queued-div'),
inputDiv = document.querySelector('.input-div'),
input = document.querySelector('.input-div input');
const colors = ['#FF7F7F', '#FFBF7F', '#FFDF7F', '#BFFF7F', '#7FFF7F', '#7FBFFF', '#7F7FFF'],
rows = document.querySelectorAll('.content__row'),
cards = document.querySelectorAll('.content__card'),
addCard = document.getElementById('addCard');
// Queued Images
const onDragStart = (event) => {
console.log('Dragging');
event.dataTransfer.setData('id', event.target.id);
setTimeout(() => {
event.target.style.visibility = 'hidden';
}, 100);
};
const onDragEnd = (event) => {
console.log('Ended dragging');
event.target.style.visibility = 'visible';
};
const displayQueuedImages = () => {
let images = '';
queuedImagesArray.forEach((image, index) => {
images += `
<div class="image" draggable="true" id="${(Date.now() + '').slice(-10) + index}">
<img width='100' height='100' style="pointerEvents:none;" id="${index}" ondragstart="onDragStart" ondragend="onDragEnd"
src="${URL.createObjectURL(image)}" alt="image" />
<span style="color:black;font-size:2rem" onclick="deleteQueuedImage(${index})">×</span>
</div>
`;
});
queuedDiv.innerHTML = images;
};
const deleteQueuedImage = (index) => {
queuedImagesArray.splice(index, 1);
displayQueuedImages();
};
input.addEventListener('change', () => {
const files = input.files;
for (let i = 0; i < files.length; i++) {
queuedImagesArray.push(files[i]);
}
queuedForm.reset();
displayQueuedImages();
});
inputDiv.addEventListener('drop', (e) => {
e.preventDefault();
const files = e.dataTransfer.files;
for (let i = 0; i < files.length; i++) {
if (!files[i].type.match('image')) return;
if (queuedImagesArray.every((image) => image.name !== files[i].name))
queuedImagesArray.push(files[i]);
}
displayQueuedImages();
});
const onDrag = (event) => {
event.preventDefault();
};
// Problem here
const onDrop = (event) => {
event.preventDefault();
const draggedCardId = event.dataTransfer.getData('id'); // nothing
const draggedCard = document.getElementById(draggedCardId); // null
event.target.appendChild(draggedCard);
};
rows.forEach((row, index) => {
const label = row.querySelector('.content__label');
label.style.backgroundColor = colors[index];
row.ondragover = onDrag;
row.ondrop = onDrop;
});
<main>
<section class="section" id="section--1">
<div class="section__title">
<h2 class="section__description">Tier list app</h2>
<h3 class="section__text">Start dragging to move cards</h3>
</div>
<div class="content" id="content">
<div class="content__row">
<div class="content__label">S (The best)</div>
</div>
<div class="content__row">
<div class="content__label">A (Great)</div>
</div>
<div class="content__row">
<div class="content__label">B (Good)</div>
</div>
<div class="content__row">
<div class="content__label">C (Mediocre)</div>
</div>
<div class="content__row">
<div class="content__label">D (Bad)</div>
</div>
<div class="content__row">
<div class="content__label">E (Horrible)</div>
</div>
<!-- <div class="content__row">
<div class="content__label">F (Worst^_^)</div>
</div> -->
</div>
</section>
<form id="queued-form">
<div class="queued-div"></div>
</form>
<div class="input-div">
<p>Drag & drop images here or <span class="browse">Browse</span></p>
<input
type="file"
class="file"
multiple="multiple"
accept="image/png, image/jpeg, image/jpg"
/>
</div>
</main>
* {
margin: 0;
padding: 0;
box-sizing: inherit;
}
html {
font-size: 62.5%; // 10px = 1rem
box-sizing: border-box;
}
body {
font-family: 'Open Sans', sans-serif;
font-weight: 300;
color: #555;
line-height: 1.5;
}
.input-div {
width: 70%;
height: 200px;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
margin: 5rem auto;
border: 2px dotted black;
background-color: white;
position: relative;
.browse {
color: black;
font-weight: bold;
}
}
.file {
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
cursor: pointer;
}
.queued-div {
width: 70%;
min-height: 200px;
display: flex;
margin: 5rem auto;
justify-content: flex-start;
flex-wrap: wrap;
gap: 0.5rem;
position: relative;
border-radius: 5px;
border: 2px dotted black;
background-color: white;
.image {
height: 10rem;
border-radius: 5px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.15);
overflow: hidden;
position: relative;
&:nth-child(4n) {
margin-right: 0;
}
img {
height: 100%;
width: 100%;
}
span {
position: absolute;
top: -4px;
right: 4px;
cursor: pointer;
font-size: 22px;
color: white;
&:hover {
opacity: 0.8;
}
}
}
}
@mixin center {
display: flex;
justify-content: center;
align-items: center;
}
// SECTIONS
.section {
padding: 1.8rem 3rem;
&__title {
max-width: 80rem;
margin: 0 auto 2rem auto;
text-align: center;
text-transform: uppercase;
}
&__description {
color: lightgreen;
font-size: 1.8rem;
}
&__text {
font-size: 2.5rem;
}
&__button {
font-size: 2rem;
text-transform: uppercase;
text-decoration: none;
padding: 1rem 2rem;
display: inline-block;
border-radius: 3rem;
position: relative;
background-color: lightgreen;
color: #fff;
border: none;
cursor: pointer;
}
}
// CONTENT
.content {
width: 70vw;
min-height: 10vh;
padding: 0rem;
box-sizing: content-box;
border: 3px solid #000;
display: flex;
flex-wrap: wrap;
flex-direction: column;
margin: 0 auto;
&__row {
width: 100%;
box-sizing: content-box;
flex-wrap: wrap;
height: 8.5rem;
background-color: #1a1a17;
display: flex;
&:not(:last-child) {
border-bottom: 2px solid #000;
}
}
&__label {
font-size: 2rem;
font-weight: 400;
height: 100%;
width: 15rem;
background-color: #555;
color: #333;
border-right: 3px solid #000;
@include center;
}
&__card {
@include center;
&:focus,
&:active {
cursor: pointer;
}
}
}
When i was adding images one by one everything was fine but when i changed button to input zone i can't get anything from new images.
There is a small issue in how you create your img
elements: the ondragstart
and ondragend
event handlers aren't being assigned properly.
Currently, your img
elements look something like:
<img id="0" ondragstart="onDragStart" ondragend="onDragEnd" src=... />
However, setting ondragstart
to equal onDragStart
doesn't actually invoke the function when the event is fired. Same with ondragend
and onDragEnd
. To do so, you have to actually invoke the functions with onDragStart(event)
and onDragEnd(event)
.
This is because every HTML event handler attribute is implicitly wrapped in:
(event) => { /** the attribute value */ }
In other words, currently, your handlers are equivalent to:
(event) => { onDragStart }
// and
(event) => { onDragEnd }
instead of
(event) => { onDragStart(event) }
// and
(event) => { onDragEnd(event) }
which is given by
<img id="0" ondragstart="onDragStart(event)" ondragend="onDragEnd(event)" src=... />
So the fix is simply to fix the img
generation code to:
images += `
<div class="image" draggable="true" id="${(Date.now() + '').slice(-10) + index}">
<img width='100' height='100' id="${index}"
ondragstart="onDragStart(event)" ondragend="onDragEnd(event)"
src="${URL.createObjectURL(image)}" alt="image" />
<span style="color: black; font-size: 2rem"
onclick="deleteQueuedImage(${index})">×</span>
</div>`;