新的子元素包含父元素。在HTMLDivElement.drop

时间:2018-06-30 07:48:05

标签: javascript html css drag-and-drop

我被这个DOM异常困扰。我有div元素和一个按钮-当用户单击按钮时,会选择一个随机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放入dropzone(一个空的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和“已填充”的div,但是我确实找不到解决方案。任何帮助和残酷的批评将不胜感激:)

1 个答案:

答案 0 :(得分:0)

这是我的解决方案。 我将当前拖动的div保存在dragged变量中,并在整个文档中放置了一个drop事件,然后您可以使用该拖动的变量将其从其父节点中删除并追加到放置的元素。

我认为您可能具有相同的id多个元素,这会混淆Javascript,或者您在drop函数中使用的coloredCube变量没有返回您认为的值。我将console.log放在coloredCube上。在dataTransfer属性上运行getData方法时,我得到的是一个空字符串,这可能会导致您得到错误。

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);