#javascript #html #dom
Вопрос:
const list = document.querySelector("#List");
const list2 = document.querySelector("#List2");
list.addEventListener("click", (ev) => {
const LI = ev.target.closest("li");
list2.append(LI);
});
<ul id="List">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<ul id="List2"></ul>
этот приведенный выше код в основном переместит <li>
элемент в другой <ul>
, и я хочу создать функцию, которая восстановит перемещенный <li>
обратно в исходный <ul>
код в его исходном индексе. так , например, когда я перемещаю этот список <li>3</li>
, я хочу, чтобы функция вернула его в исходный индекс в первом <ul>
, в этом случае он будет помещен в третий индекс, который находится в середине <li>2</li>
и <li>4</li>
как я могу этого достичь?
Комментарии:
1. Что делать, если
<li>2</li>
он также был перемещен перед восстановлением<li>3</li>
? Что вы пробовали до сих пор? Есть ли фрагмент кода, которым вы можете поделиться с нами?
Ответ №1:
Вот еще один подход. Я обрабатываю все в функции обработчика одного клика. Сначала я «вспоминаю» начальную позицию, которую каждый LI
занимал в первом UL
. Когда происходит щелчок, я просто переношу LI
его в «другое» UL
. Затем, если щелчок произошел во втором UL
( if (!idx) ...
), я снова переставляю элементы в первом UL
, сортируя их и повторно вставляя в UL
.
const lists = [...document.querySelectorAll("ul.pickable")];
[...lists[0].children].forEach((li,i)=>li.dataset.n=i); // remember original order
document.addEventListener("click", ev => {
const LI = ev.target.closest("li");
if (LI?.parentNode.classList.contains("pickable")) { // only, if the click happened within a `LI` element ...
const idx=lists.indexOf(LI.parentNode),
UL = lists[1-idx];
UL.append(LI);
if (idx) [...UL.children].sort((a,b)=>a.dataset.n-b.dataset.n)
.forEach(li=>UL.append(li))
}
});
<ul class="pickable">
<li>this</li>
<li>order</li>
<li>should</li>
<li>be</li>
<li>kept</li>
</ul>
<ul class="pickable"></ul>
Я мог бы просто опустить, if (idx)
если бы хотел LI
, чтобы s были отсортированы в обоих UL
s в «исходном» порядке.
Ответ №2:
Вам, вероятно, придется запомнить некоторую информацию о том, где вы ее взяли. Есть несколько вариантов:
- Если вы собираетесь переместить только один
li
из них, вы можете запомнить егоnextSibling
элемент, а затем использоватьinsertBefore
в списке, передав этуnextSibling
ссылку для «ссылочного элемента». Но если вы также собирались переместить другие элементы, это может не сработать, потому что родного брата после этого может больше не быть. - Если вы хотите сделать это по индексу, вам нужно запомнить, какова была позиция элемента в его родительском элементе. Я не думаю, что DOM дает вам прямой способ получить эту информацию, но вы можете найти ее достаточно легко, обратившись
Array.prototype.indexOf
к родительскойchildren
коллекции. - Расположите элементы в порядке, который мы можем определить по их содержимому (у них такой порядок в вопросе), и вставьте элемент там, где он должен быть в этом порядке. Не нужно запоминать ничего особенного, потому что оно несет в себе свое содержание.
Вот пример индексного подхода, поскольку вы упомянули об этом в вопросе; см. Комментарии:
const list = document.querySelector("#List");
const list2 = document.querySelector("#List2");
list.addEventListener("click", (ev) => {
const li = ev.target.closest("li");
// Find its index in its parent's `children` collection
const index = Array.prototype.indexOf.call(li.parentElement.children, li);
// Save that as an attribute
li.setAttribute("data-index", index);
list2.append(li);
});
list2.addEventListener("click", (ev) => {
const li = ev.target.closest("li");
// Get the index, if it has one
let index = li.getAttribute("data-index");
// Add at the end if no index or it's out of range
const maxIndex = list.children.length;
if (isNaN(index) || index > maxIndex) {
index = maxIndex;
}
// Get the element that will be after it
const nextSibling = list.children[index] || null;
// Insert before it (if `nextSibling` is `null`, inserts at the end)
list.insertBefore(li, nextSibling);
li.removeAttribute("data-index");
});
<ul id="List">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<ul id="List2"></ul>
Комментарии:
1. Это не всегда работает надежно. Положение каждого
LI
элемента определяется только при нажатии на него. К тому времени он, возможно, уже переместился на вершину. Пролистайте пример, и вы сами это заметите. (Начните с того, что сначала нажмите на верхние элементы.)2. @cars10m — Это правда, я не утверждал, что это было все, конец всему; скорее отправная точка. Ваш подход к запоминанию всех начальных индексов является хорошей альтернативой. Я думаю, что если бы я делал это, я бы использовал некоторый естественный порядок элементов, основанный на их содержании (мой третий вариант выше).
3. @cars10m хм, да, я только что понял, что возникнет несколько проблем, если я сделаю это с помощью индексов