Если я использую статические изображения в HTML, API Drag n drop работает, но мне нужно добавить свойства к изображениям, чтобы позже манипулировать этими свойствами с помощью JS (изображения посвящены играм, и я хочу добавить цену, идентификатор, имя и т. д. ), поэтому я создал JSON, содержащий изображения и свойства. Я извлекаю этот JSON и получаю изображения, которые собираюсь перетащить в div с помощью JS. Когда дело доходит до события «dragstart», оно не работает, и я не получаю никаких ошибок, когда начинаю перетаскивать изображение. Изображения присутствуют, когда выборка завершена, но Chrome или даже Firefox не читают их, когда я начинаю перетаскивать. Я принимаю любые комментарии и буду благодарен за любой ответ. Вот мой JS:
document.addEventListener('DOMContentLoaded', iniciarApp );
function iniciarApp() {
var contenedor = document.querySelector('#contenedor');
var narrowDiv = document.querySelector('#narrow');
obtenerDatos();
function obtenerDatos() {
const url = 'data/productos.json';
fetch(url)
.then( respuesta => respuesta.json())
.then( resultado => cargarImgNarrow(resultado))
}
function cargarImgNarrow(imagenes = []) {
imagenes.forEach( img => {
const { imagen, precio, nombre, id } = img;
var productoImg = document.createElement('IMG');
productoImg.src = imagen;
productoImg.value = precio;
productoImg.name = nombre;
productoImg.id = id;
productoImg.alt = "imagen";
productoImg.draggable = true;
productoImg.classList.add('draggable', 'drag-item');
narrowDiv.appendChild(productoImg);
})
}
var draggableElements = document.querySelectorAll(".draggable");
draggableElements.forEach(elem => {
elem.addEventListener("dragstart", (event) => dragStart(event));
})
// drag andr drop functions
function dragStart(event) {
console.info("Dragging...")
event.dataTransfer.setData("text/plain", event.target.id);
// event.dataTransfer.setData("text", event.target.value);
}
}
querySelectorAll()
вызывается до или даже во время срабатывания DOMContentLoaded
Event
. Если бы HTMLElement
из NodeList
, которые вы извлекаете, были статическими, это не было бы проблемой. Но поскольку он динамичен, HTMLElement
еще не существует, когда querySelectorAll()
вызывается. Результат — пустой NodeList
. Вы можете убедиться в этом сами, добавив фрагмент:
draggableElements.forEach(elem => {
console.info(elem)
/* •••Rest of code••• */
}
Я не понимаю, что мешает вам добавить прослушиватель событий непосредственно в созданный вами HTMLElement
, учитывая, что они все еще у вас есть. Избегаются затраты на получение NodeList
.
function cargarImgNarrow(imagenes = []) {
imagenes.forEach(img => {
/* •••Rest of code••• */
productoImg.addEventListener("dragstart", event => dragStart(event));
})
}
Вы можете просто добавить прослушиватель событий к родительскому элементу, например #narrow
. Целью события по-прежнему будет изображение, поскольку это единственный элемент, перетаскивание которого разрешено.
Кстати: не определяйте функцию внутри функции. Предварительное определение функции не является проблемой, даже если она обрабатывает элементы в DOM. Вам просто нужно дождаться загрузки DOM, прежде чем вызывать функцию.
var narrowDiv, contenedor;
document.addEventListener('DOMContentLoaded', iniciarApp);
function iniciarApp() {
contenedor = document.querySelector('#contenedor');
narrowDiv = document.querySelector('#narrow');
narrowDiv.addEventListener("dragstart", dragStart);
obtenerDatos();
}
function obtenerDatos() {
let url = 'data:application/json,[{"imagen":"/img01.png","precio":123,"nombre":123,"id":1},{"imagen":"/img02.png","precio":123,"nombre":123,"id":2}]';
fetch(url)
.then(respuesta => respuesta.json())
.then(resultado => cargarImgNarrow(resultado));
}
function cargarImgNarrow(imagenes = []) {
imagenes.forEach(img => {
const {
imagen,
precio,
nombre,
id
} = img;
var productoImg = document.createElement('IMG');
productoImg.src = imagen;
productoImg.value = precio;
productoImg.name = nombre;
productoImg.id = id;
productoImg.alt = "imagen"+imagen;
productoImg.draggable = true;
productoImg.classList.add('draggable', 'drag-item');
narrowDiv.appendChild(productoImg);
});
}
// drag andr drop functions
function dragStart(event) {
event.dataTransfer.setData("text/plain", event.target.id);
console.info("Dragging... id:",event.target.id);
// event.dataTransfer.setData("text", event.target.value);
}
<div id = "contenedor"></div>
<div id = "narrow"></div>
изменение позиции forEach решило проблему. Спасибо, мистер Кэнон!