无法通过DOM将两个添加的元素拖到不同的位置

时间:2019-05-25 14:47:25

标签: javascript function dom

我正在尝试创建一个看板(类似于trello)的简单网站来学习javascript。我已经使用了拖放功能,但是,我正努力添加新卡,并将多张卡移动到不同列表中的不同位置。

第一张卡(从头开始在HTML中实现,而不是由DOM添加)可以正常工作。我可以将这张卡移动到任何需要的地方。

我的代码有两个问题:

  1. 我创建了两个名为addCard()addTaskContainer()的函数,以便能够添加新任务。元素被创建,但是每当我尝试移动此卡时,第一张原始卡将被移到放置位置,而不是DOM被创建。
  2. 如果我尝试通过addCard()函数添加多张卡片,则该卡片似乎堆叠在同一div中。我意识到我需要删除最初添加的ID,但是如果再次按下该按钮,我将无法添加新的ID。

我希望包含不同卡的列表始终为新添加的卡提供+1任务容器。

我尝试在addTaskContainer()函数中设置id = "";的{​​{1}},但是在单击按钮时无法将其重新添加到addCard()

我还尝试过像这样遍历卡片中的卡片:

addTaskContainer()

和类似的卡片:

for (const card in cards) {
    card.addEventListener('dragstart', dragStart);
    card.addEventListener('dragend', dragEnd);
}

没有运气。

html

for (const card of cards) {
    card.addEventListener('dragstart', dragStart);
    card.addEventListener('dragend', dragEnd);
}

javscript

<div class="lists">
    <div class="list">
        <div class="list-header">
              <p>Backlog</p>
        </div>
        <div class="list-body" id="backlog">
              <p>body</p>
              <div class="taskContainer">
                  <div class="card" draggable="true"> </div>
              </div>
              <div class="taskContainer">
                   <div class="card" draggable="true"> </div>
              </div>
              <div class="taskContainer">
              </div>
         </div>
         <div class="list-footer">
              <p>footer</p>
              <button onclick="addCard()">Add ned card</button>
         </div>
     </div>
</div>

2 个答案:

答案 0 :(得分:1)

您发布的代码存在两个问题:

  • 您使用id来标识元素,页面上每个id只能有一个元素。这意味着当您通过id获得元素时,它可能是旧卡片。一种方法是在完成拖动操作后删除ID,但更简单的方法是将卡存储在变量draggingCard

  • 您没有将侦听器添加到函数中新创建的cardstaskContainers中。

我还添加了一些样式,以使所有内容更易于查看: https://codepen.io/anon/pen/XwqpKg

HTML:

<div class="lists">
    <div class="list">
        <div class="list-header">
            <p>Backlog</p>
        </div>
        <div class="list-body" id="backlog">
            <p>body</p>
            <div class="taskContainer">
                <div class="card" draggable="true"> </div>
            </div>
            <div class="taskContainer">
                <div class="card" draggable="true"> </div>
            </div>
            <div class="taskContainer">
            </div>
        </div>
        <div class="list-footer">
            <p>footer</p>
            <button onclick="addCard()">Add ned card</button>
        </div>
    </div>
</div>

CSS:

.card {
    display: inline-block;
    padding: 8px;
    cursor: pointer;

    border-radius: 4px;
    box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.25);
}

.card-dragging {
    display: absolute;
}

.taskContainer {
    display: inline-block;
    background: skyblue;
    padding: 8px;
    min-width: 16px;
    min-height: 16px;
}

JavaScript:

const card = document.querySelector('.card');
const cards = document.querySelectorAll('.card')
const taskContainers = document.querySelectorAll('.taskContainer');

var draggingCard = null;

// card listeners
cards.forEach(addCardListeners);

// Loop through taskContainer boxes and add listeners
taskContainers.forEach(addContainerListeners);

// Drag Functions
function dragStart(event) {
    this.className += ' hold';
    setTimeout(() => (this.className = 'invisible'), 0); //set timeout so card wont dissapear
    draggingCard = event.target;
}

function dragEnd() {
    this.className = 'card';
    draggingCard = null;
}

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

function dragEnter(e) {
    e.preventDefault();
    this.className += ' hover';
}

function dragLeave() {
    this.className = 'taskContainer';
}

function dragDrop() {
    this.className = 'taskContainer';
    this.append(draggingCard);
}

//add card function
function addTaskContainer() {
    var taskContainer = document.createElement('div');
    taskContainer.className = "taskContainer";
    taskContainer.id = "add-new-card";
    addContainerListeners(taskContainer);
    document.getElementById("backlog").append(taskContainer);
    return taskContainer;
}

function addCard() {
    var container = addTaskContainer();
    var card = document.createElement('div');
    card.className = "card";
    card.id = "new-card";

    card.setAttribute('draggable', true);
    addCardListeners(card);
    container.appendChild(card);
}

function addCardListeners(card) {
card.addEventListener('dragstart', dragStart);
card.addEventListener('dragend', dragEnd);
}

function addContainerListeners(taskContainer) {
    taskContainer.addEventListener('dragover', dragOver);
    taskContainer.addEventListener('dragenter', dragEnter);
    taskContainer.addEventListener('dragleave', dragLeave);
    taskContainer.addEventListener('drop', dragDrop);
}

答案 1 :(得分:-1)

部分原因是您的投递处理程序仅设计用于处理页面上的第一张卡片。 this.append(card)将始终将第一张卡片添加到放置区域。您需要检索拖动的元素,然后附加该元素。

正如您将在MDN示例中观察到的那样,在拖动开始事件处理程序中,设置了一个全局变量来标识要拖动的元素。然后,稍后将“拖放”元素附加到放置区。

MDN Example Here

相关代码:

    var dragged;
    document.addEventListener("dragstart", function(event) {
      // store a ref. on the dragged elem
      dragged = event.target;
      event.target.style.opacity = .5;
    }, false);
    document.addEventListener("drop", function(event) {
      // prevent default action (open as link for some elements)
      event.preventDefault();
      // move dragged elem to the selected drop target
      if (event.target.className == "dropzone") {
        event.target.style.background = "";
        dragged.parentNode.removeChild( dragged );
        event.target.appendChild( dragged );
      }
    }, false);

这是您想要做的事情:

https://jsfiddle.net/vyr7ewbs/2/