If you drag the green square over one of the other squares it inserts it before (moves it), but if you continue to drag without letting go of your mouse button, this action doesn’t continue to work for the remaining squares. The onpointermove
event only fires when over the green button itself, not the rest of the DOM at this point.
I presume this is something to do with the fact it’s moved in the DOM, any ideas how to work around this? I have to use the Pointer Capture API to perform this action.
const divs = Array.from(document.querySelectorAll("div"));
divs.forEach((div) => {
function beginSliding(e) {
div.onpointermove = slide;
div.setPointerCapture(e.pointerId);
}
function stopSliding(e) {
div.onpointermove = null;
div.releasePointerCapture(e.pointerId);
}
function slide(e) {
const ele = document.elementFromPoint(e.clientX, e.clientY);
console.log("move");
if (ele === e.target || !divs.includes(ele)) {
return;
}
div.parentElement.insertBefore(div, ele)
}
div.onpointerdown = beginSliding;
div.onpointerup = stopSliding;
});
nav {
display: flex;
gap: 10px;
}
div {
height: 30px;
width: 100px;
user-select: none;
}
#a { background: grey; }
#b { background: red; }
#c { background: blue; }
#d { background: yellow; }
#e { background: green; }
<nav>
<div id="a"></div>
<div id="b"></div>
<div id="c"></div>
<div id="d"></div>
<div id="e"></div>
</nav>
JSFiddle https://jsfiddle.net/u7f2taLj/2/
2
Answers
It seems that
setPointerCapture
is sensitive to the location of the element. A work around would be tobeginSliding
again as soon as possible after changing location.To improve the code I use
insertAfter
instead ofinsertBefore
when needed, depending in the order of the elements.Copy "div.setPointerCapture(e.pointerId);" after "div.onpointerdown = beginSliding;" in slide function : lines 52 & 53