Невозможно перетащить два добавленных элемента через DOM в разные места - PullRequest
0 голосов
/ 25 мая 2019

Я пытаюсь создать простой веб-сайт, похожий на канбан (трэлло), для изучения javascript. Я получил работоспособность перетаскивания, но я пытаюсь добавить новую карту и переместить несколько карт в разные места в разных списках.

Первая карта (которая реализована в HTML с нуля, а не добавлена ​​DOM), работает нормально. Я могу переместить эту карту куда угодно.

У меня две проблемы с моим кодом:

  1. Я создал две функции с именами addCard() и addTaskContainer(), чтобы иметь возможность добавлять новые задачи. Элемент создается, но всякий раз, когда я пытаюсь переместить эту карту, первая, оригинальная карта перемещается в выброшенную позицию, а не DOM, создавшую ее.
  2. Если я пытаюсь добавить несколько карт с помощью функции addCard(), кажется, что они просто складываются в один и тот же div. Я понимаю, что мне нужно удалить начальный добавленный идентификатор, но я изо всех сил пытаюсь это сделать, хотя могу добавить новый идентификатор, если кнопка будет нажата снова.

Я хочу, чтобы в списках, содержащих разные карточки, всегда был доступен +1 контейнер задач для вновь добавленной карточки.

Я попытался установить addTaskContainer() id = ""; в функции addCard(), но не смог добавить его обратно к addTaskContainer() при нажатии кнопки.

Я также пробовал проходить по карточкам в карточках, например:

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

и карточная карточка вот так:

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

без удачи.

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>

javscript

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

// card listeners
card.addEventListener('dragstart', dragStart);
card.addEventListener('dragend', dragEnd);

// Loop through taskContainer boxes and add listeners
for (const taskContainer of taskContainers) {
    taskContainer.addEventListener('dragover', dragOver);
    taskContainer.addEventListener('dragenter', dragEnter);
    taskContainer.addEventListener('dragleave', dragLeave);
    taskContainer.addEventListener('drop', dragDrop);
}

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

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

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(card);
}

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

function addCard() {
    addTaskContainer();
    var card = document.createElement('div');
    card.className = "card";
    card.id = "new-card";
    document.getElementById("add-new-card").appendChild(card);
    document.getElementById("new-card").setAttribute('draggable', true);
}

Ответы [ 2 ]

1 голос
/ 25 мая 2019

было две проблемы с кодом, который вы отправили:

  • Вы использовали id для идентификации элемента, на странице может быть только один элемент с каждым id. Это означает, что когда вы получили элемент по id, это может быть старая карта. Одним из способов будет удаление идентификатора, когда вы закончите перетаскивание, но более простым способом является сохранение карты в переменной draggingCard

  • Вы не добавляли слушателей во вновь созданные cards и taskContainers в своих функциях.

Я также добавил немного стилей, чтобы все было легче увидеть: 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);
}
0 голосов
/ 25 мая 2019

Частично причина в том, что ваш обработчик дропа предназначен только для самой первой карты на странице.this.append(card) всегда добавит эту первую карту в зону сброса.Вам нужно извлечь перетаскиваемый элемент и добавить вместо него этот элемент.

Как вы увидите в примере MDN, в обработчике события начала перетаскивания установлена ​​глобальная переменная, определяющая, какой элемент перетаскивается.Затем, позже этот «перетаскиваемый» элемент добавляется в зону сброса.

MDN Пример здесь

Соответствующий код:

    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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...