Как сохранить новую позицию html после перетаскивания?

#javascript #html #jquery #local-storage #domparser

Вопрос:

Я работаю над проектом, в котором у меня есть перетаскиваемые карты, которые можно разместить только в 7 определенных областях размещения.

Я могу перетаскивать карточки и размещать их в новых областях, но как только я перезагружаю страницу, позиции не сохраняются.

На «падение» событием, я пытался спасти весь новый див (выпавших карт новые позиции и размещения 8 районов), которая создается динамически после того, как я «капля» с карты на локальном хранилище, используя «outerHTML» localstorage.setItem('newCardDashboardDiv', cardDashboard.outerHTML) , и данные, кажется, быть правильно сохранены в локальном хранилище в виде строки (т. е. он сохраняет весь div, в том числе обновленный внутренний div, который будет содержать HTML-элементов карты после перетаскивания и помещается в любом размещения зон с 1 по 7).

Я попытался вытащить весь div из данных локального хранилища и установить его в качестве нового значения html const newDashboardDiv = localstorage.getItem('newCardDashboardDiv) $("#cardDashboardDiv).replaceWith(newDashboardDiv) , но это просто не сработает. Я чувствую, что перепробовал все.

Использование outerHTML, похоже, удаляет все стили и функциональные элементы исходного HTML, как только я извлекаю эти данные outerHTML из локального хранилища. Размещение новой карты на самом деле экономит при обновлении, но она выделена серым цветом, и я больше не могу перетаскивать карту в любую новую область размещения.

Кстати, я использую Chrome.

Вот мой код

HTML

 <section id="cardFrameworkDashboard">
<div id="cardDashboardRow" class="container-fluid cardDashboardRow">
  <div id="replaceDash" class="row mt-5">
    <div class="cardPlacementArea" style="width: 30rem; height: 20rem; margin-right: 5rem;">
      <div class="card-body cardContent" draggable="false">
        <h5 class="card-title">System Messages Card</h5>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
        <a href="#" class="card-link">Card link</a>
        <a href="#" class="card-link">Another link</a>
      </div>
    </div>
    <div id="placementArea1" class="cardPlacementArea" style="width: 30rem; height: 20rem; margin-right: 5rem;">
      <div id="droppable1" class="card-body cardContent" draggable="true">
        <h5 class="card-title">Content Card 1</h5>
        <h6 class="card-subtitle mb-2 text-muted">Card subtitle</h6>
        <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
        <a href="#" class="card-link">Card link</a>
        <a href="#" class="card-link">Another link</a>
      </div>
    </div>
    <div id="placementArea2" class="cardPlacementArea" style="width: 30rem; height: 20rem; margin-right: 5rem;">
    </div>
    <div id="placementArea3" class="cardPlacementArea" style="width: 30rem; height: 20rem;">
    </div>
  </div>
  <div class="row mt-5">
    <div id="placementArea4" class="cardPlacementArea" style="width: 30rem; height: 20rem; margin-right: 5rem;">
    </div>
    <div id="placementArea5" class="cardPlacementArea" style="width: 30rem; height: 20rem; margin-right: 5rem;">
    </div>
    <div id="placementArea6" class="cardPlacementArea" style="width: 30rem; height: 20rem; margin-right: 5rem;">
    </div>
    <div id="placementArea7" class="cardPlacementArea" style="width: 30rem; height: 20rem;">
    </div>
  </div>
</div>
 

Язык JavaScript

 const cardContentDraggables = document.querySelectorAll('.cardContent')
const cardPlacements = document.querySelectorAll('.cardPlacementArea')
const cardDashboard = document.querySelector('.cardDashboardRow')

cardContentDraggables.forEach(cardContentDraggable => {
    cardContentDraggable.addEventListener("dragstart", () => {
        cardContentDraggable.classList.add("dragging")
    })

    cardContentDraggable.addEventListener("dragend", () => {
        cardContentDraggable.classList.remove("dragging")
    })

    cardPlacements.forEach(cardPlacement => {
        cardPlacement.addEventListener("dragover", event => {
            event.preventDefault()
            const draggable = document.querySelector(".dragging")
            cardPlacement.append(draggable)
        })
        cardPlacement.addEventListener("dragstart", dragStart)
        cardPlacement.addEventListener("dragend", dragEnd)
        cardContentDraggable.addEventListener('drop', () => {
            localStorage.setItem('newCardDashboardDiv', cardDashboard.outerHTML)
            console.log('position saved to ls')
        })
    })
})

function dragStart() {
    for (var i = 0; i < cardPlacements.length; i  ) {
        cardPlacements[i].classList.add("cardPlacementAreaDrag")
    }
}

function dragEnd() {
    for (var i = 0; i < cardPlacements.length; i  ) {
        cardPlacements[i].classList.remove("cardPlacementAreaDrag")
    }
}
 

jQuery

   $(document).ready(function () {
    const newDashboardDiv = localStorage.getItem('newCardDashboardDiv')
    console.log('success got div from ls')
    $(window).bind("beforeunload", function (event) {
      event.preventDefault()
      console.log('detected refresh')
    })
    $(window).on('load', function (event) {
      event.preventDefault()
      console.log('after refresh')
      $("#cardDashboardRow").replaceWith(newDashboardDiv)
    })
})
 

Ответ №1:

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

Как только вы перезагрузите свою страницу, эти изменения исчезнут, как вы уже сказали. Это имеет некоторый смысл, поскольку страница полностью отрисовывается заново, начиная с исходного исходного кода. Хранение полного div и перетаскиваемых элементов внутри кажется мне немного чрезмерным, так как все, что вы хотите сделать, — это просто немного отсортировать, верно?

Как насчет того, чтобы дать вашим картам что-то, чтобы сделать их различимыми, например, идентификатор или конкретный (пронумерованный?) класс? После перетаскивания вы можете просто сохранить положение (какую область, какую позицию) каждой карты и «переместить» их обратно на место после перезагрузки …

Комментарии:

1. Я думаю, ты на что-то наткнулся… итак, допустим, я даю html-карте 1 идентификатор=»movableCard1″. Затем, если он будет перемещен в область размещения 3, он будет помещен внутри элемента div области размещения 3. Тогда как бы я сохранил позицию карты 1? На основе значений стиля css?

2. Вот почему я попытался сохранить весь div в локальном хранилище. Потому что нет значения стиля css (например, вверху и слева), на котором я мог бы основываться. Это не свободное течение. Карточке присваивается класс «перетаскивания» при «запуске перетаскивания», и как только «перетаскивание» происходит над областью размещения, она добавляется к этой области размещения

3. Просто найдите систему для хранения позиции каждой карты, которая наилучшим образом соответствует вашим потребностям и предпочтениям. Например, «карта 1, область 5, позиция 3». Поместите это в объект js и сохраните его в локальном хранилище. Напишите сценарий, который перемещает ваши карты в сохраненные позиции. Готово 😉