Подскажите, реализуемо ли это при помощи jQuery
Возможно в другом ответе подскажут, я уже плоховато соображаю, ваш код так и не завёл без ошибок.
как сделать подобное на JavaScript
А вот на это отвечу.
Воспользуемся нативным drag and drop API в HTML5. Уже 23 год, вряд ли вам нужна реализация на HTML4, хотя если JQuery используете, всякое возможно.
document.addEventListener("DOMContentLoaded", function() {
let draggedElement;
document.addEventListener("dragstart", function(event) {
draggedElement = event.target;
});
document.addEventListener("dragover", function(event) {
event.preventDefault();
});
document.addEventListener("drop", function(event) {
event.preventDefault();
if (event.target.classList.contains("dragElement")) {
const targetValue = event.target.querySelector("input").value;
const draggedValue = draggedElement.querySelector("input").value;
event.target.querySelector("input").value = draggedValue;
draggedElement.querySelector("input").value = targetValue;
}
});
});
<div id="parent" style="border:1px solid black">
<div class="dragElement" style="border:1px solid black" draggable="true">
<input value="Drag and drop 1">
</div>
<div class="dragElement" style="border:1px solid black" draggable="true">
<input value="Drag and drop 2">
</div>
<div class="dragElement" style="border:1px solid black" draggable="true">
<input value="Drag and drop 3">
</div>
</div>
Когда начинается перетаскивание, сохраняем элемент в переменную draggedElement
. При событии drop
, проверяем, является ли целевой элемент элементом с классом dragElement
. Если это так, то меняем значения их инпутов местами.
Да, здесь пользуемся классом, но это ваше ограничение не совсем понимаю:
Количество инпутов будет генерироваться автоматически, поэтому поменять местами при помощи имен классов или id не представляется возможным.
Множьте сколько угодно, класс то у них одинаковый будет. И атрибут draggable
необходимо добавить.
По комментариям. Вот пример на interact:
interact('.dragElement')
.draggable({
listeners: {
start(event) {
const target = event.target;
const isDraggable = target.getAttribute('data-draggable') === 'true';
if (!isDraggable) {
event.preventDefault();
}
},
move(event) {
const target = event.target;
if (!target.getAttribute('data-draggable') === 'true') {
return;
}
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
},
end(event) {
const target = event.target;
if (!target.getAttribute('data-draggable') === 'true') {
return;
}
target.removeAttribute('data-x');
target.removeAttribute('data-y');
const targetValue = target.querySelector('input').value;
const siblings = [...target.parentNode.children].filter(
(el) => el !== target
);
const nearestElement = siblings.reduce((prev, curr) => {
const prevRect = prev.getBoundingClientRect();
const currRect = curr.getBoundingClientRect();
return Math.abs(currRect.top - prevRect.top) <
Math.abs(target.getBoundingClientRect().top - prevRect.top) ?
curr :
prev;
});
const draggedValue = nearestElement.querySelector('input').value;
target.querySelector('input').value = draggedValue;
nearestElement.querySelector('input').value = targetValue;
target.style.transform = ''; // Reset transform after swapping
},
},
});
<script src="https://cdn.jsdelivr.net/npm/interactjs@1.10.11/dist/interact.min.js"></script>
<div id="parent" style="border: 1px solid black">
<div class="dragElement" style="border: 1px solid black">
<input value="Drag and drop 1">
</div>
<div class="dragElement" style="border: 1px solid black">
<input value="Drag and drop 2">
</div>
<div class="dragElement" style="border: 1px solid black">
<input value="Drag and drop 3">
</div>
</div>
Тут уже с Android работает. Немного кривовато, но всё же :)
Вопрос то не об этом был.