Новый дочерний элемент содержит родительский элемент. на HTMLDivElement.drop - PullRequest
0 голосов
/ 30 июня 2018

Я застрял с этим исключением DOM. У меня есть элементы div и кнопка - когда пользователь нажимает на кнопку, выбирается случайный div, к которому добавляется другой div. Этот другой div имеет класс с установленным фоновым цветом. Другими словами, когда пользователь нажимает кнопку, случайный контейнер div заполняется другим случайным цветным div. Затем я хочу, чтобы пользователь мог перетащить этот вновь созданный и окрашенный div в пустой. Вот тут и возникает проблема. Вот моя разметка:

<div class="row">
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
</div>

После нажатия кнопки (добавляется новый элемент div) это выглядит так:

 <div class="row">
    <div class="empty border"></div>
    <div class="empty border">
        <div class="filled" draggable="true" id="test
        style="background-color: rgb(242, 202, 185);"></div>
    </div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
    <div class="empty border"></div>
 </div>

Итак, когда «заполненный» div сбрасывается в зону сброса (пустой div), я получаю это необученное исключение. Вот мой JS:

const prepareForDrag =  () => {
let divElements = Array.from(document.getElementsByTagName('div'));
let emptyCubes = divElements.filter(cube =>    cube.classList.contains('empty'));
let filledCubes = divElements.filter(cube => cube.classList.contains('filled'));

emptyCubes.forEach(function (cube) {
    cube.addEventListener('dragover', dragOver);
    cube.addEventListener('drop', drop);
})

filledCubes.forEach(function (cube) {
    cube.addEventListener('dragstart', dragStart);
})

function dragStart (e) {
    emptyCubes.forEach(cube => cube.classList.add('dropzone-border'));
    e.dataTransfer.setData('text/plain', e.target.getAttribute('id'));
}

function dragOver (e) {
    e.preventDefault();
}


function drop (e) {
    let coloredCube = e.dataTransfer.getData('text/plain');
    e.target.appendChild(document.getElementById(coloredCube));
    emptyCubes.forEach(cube => cube.classList.remove('dropzone-border'));
}
}

Я ясно понимаю, что когда я отпускаю кнопку мыши, она пытается добавить родительский div и заполненный, но я действительно не могу найти решение. Буду очень признателен за любую помощь и жестокую критику:)

1 Ответ

0 голосов
/ 30 июня 2018

Вот мое решение. Я сохраняю текущий перетаскиваемый div в переменной dragged и помещаю событие drop на весь документ, затем вы можете использовать эту перетаскиваемую переменную, чтобы удалить ее из родительского узла и добавить к удаленному элементу.

Я думаю, что у вас либо несколько элементов с одинаковым id, что вводит в заблуждение Javascript, либо переменная coloredCube, которая есть в функции удаления, не возвращает значение, которое вы считаете правильным. Я бы поставил console.log на цветном кубе. Я получаю пустую строку, когда запускаю метод getData для свойства dataTransfer, что может привести к получаемой вами ошибке.

let dragged;

function appendDiv(e) {
    e.preventDefault();
    const emptyDivs = Array.from(document.getElementsByClassName('empty'));
    const newDiv = document.createElement('div');
    newDiv.classList = 'filled';
    newDiv.draggable = true;
    newDiv.style.backgroundColor="red";
    newDiv.style.height = "50px";
    newDiv.style.width = "50px";
    newDiv.addEventListener('dragstart', dragStart);
    newDiv.addEventListener('dragend', dragEnd);
    // Should add to a random empty div. I just picked one to add it.
    emptyDivs[1].appendChild(newDiv); 
}

function dragStart(e){
    dragged = e.target;
    e.target.style.opacity = .5;
    e.dataTransfer.setData('text/plain', null);
}

function dragEnd(e){
    e.target.style.opacity = "";
}

function handleDrop(e){
    e.preventDefault();
    dragged.parentNode.removeChild(dragged);
    e.target.appendChild(dragged);
}

function dragOver(e){
    e.preventDefault();
}

document.addEventListener('drop', handleDrop);

Array.from(document.getElementsByClassName('empty')).forEach(emptyDiv => {
    emptyDiv.addEventListener('dragover', dragOver);
});


document.getElementById('btn-append').addEventListener('click', appendDiv);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...