I am working on a sortable list, I am very new to javascript, I am able to vertically drag and drop. but i am not able do the same for horizontally. I saw a tutorial completed this.
For horizontal do i need to use X axis? If somebody can help me out with this code.
From what I can tell, the drop, along with the dragstart and dragend events, only are aware of the element they are going into. They can't tell if the mouse is on the top half of the dropzone, or the bottom half. How to basically create dropzone and switch element in case of horizontal
I want to create something like this
I don't want to do swapping between the words.
const list = document.querySelector('.list')
const listItems = document.querySelectorAll('.list-item')
// let dragIndex, dragSource
const getMouseOffset = (evt) => {
const targetRect = evt.target.getBoundingClientRect()
const offset = {
x: evt.pageX - targetRect.left,
y: evt.pageY - targetRect.top
}
return offset
}
const getElementVerticalCenter = (el) => {
const rect = el.getBoundingClientRect()
return (rect.bottom - rect.top) / 2
}
const appendPlaceholder = (evt, idx) => {
evt.preventDefault()
if (idx === dragIndex) {
return
}
const offset = getMouseOffset(evt)
const middleY = getElementVerticalCenter(evt.target)
const placeholder = list.children[dragIndex]
// console.log(`hover on ${idx} ${offset.y > middleY ? 'bottom half' : 'top half'}`)
if (offset.y > middleY) {
list.insertBefore(evt.target, placeholder)
} else if (list.children[idx + 1]) {
list.insertBefore(evt.target.nextSibling || evt.target, placeholder)
}
return
}
function sortable(rootEl, onUpdate) {
var dragEl;
// Making all siblings movable
[].slice.call(rootEl.children).forEach(function (itemEl) {
itemEl.draggable = true;
});
// Function responsible for sorting
function _onDragOver(evt) {
evt.preventDefault();
evt.dataTransfer.dropEffect = 'move';
var target = evt.target;
if (target && target !== dragEl && target.nodeName == 'DIV') {
// Sorting
const offset = getMouseOffset(evt)
const middleY = getElementVerticalCenter(evt.target)
if (offset.y > middleY) {
rootEl.insertBefore(dragEl, target.nextSibling)
} else {
rootEl.insertBefore(dragEl, target)
}
}
}
// End of sorting
function _onDragEnd(evt){
evt.preventDefault();
dragEl.classList.remove('ghost');
rootEl.removeEventListener('dragover', _onDragOver, false);
rootEl.removeEventListener('dragend', _onDragEnd, false);
// Notification about the end of sorting
onUpdate(dragEl);
}
// Sorting starts
rootEl.addEventListener('dragstart', function (evt){
dragEl = evt.target; // Remembering an element that will be moved
// Limiting the movement type
evt.dataTransfer.effectAllowed = 'move';
evt.dataTransfer.setData('Text', dragEl.textContent);
// Subscribing to the events at dnd
rootEl.addEventListener('dragover', _onDragOver, false);
rootEl.addEventListener('dragend', _onDragEnd, false);
setTimeout(function () {
// If this action is performed without setTimeout, then
// the moved object will be of this class.
dragEl.classList.add('ghost');
}, 0)
}, false);
}
// Using
sortable(list, function (item) {
console.log(item);
});
.list {
padding: 1rem;
}
.ghost {
opacity: 1;
}
.list-item {
background: #8bb3f4;
padding: 0.5rem;
border: 1px solid white;
margin: 1px 0;
}
.placeholder {
display: none;
background: #303742;
pointer-events: none;
}
<div class="list">
<div class="list-item" draggable=true>
Item 1
</div>
<div class="list-item" draggable=true>
Item 2
</div>
<div class="list-item" draggable=true>
Item 3
</div>
<div class="list-item" draggable=true>
Item 4
</div>
</div>
