3

I've created a video player progress bar on codesandbox.io (https://codesandbox.io/s/seekbar-with-thumbnail-and-time-tooltips-forked-h5x8k?file=/src/Progressbar.tsx), which is working fine on chrome but not on other browsers.

Specially on firefox the progressbar slider isn't working, dragStart and dragEnd event are firing just fine but not the onDrag event.

onDrag event has all the wrong values for clientX clientY etc.

After some googling Ive found about dataTransfer and added that to drag start event handler too...

event.dataTransfer.setData("application/x-moz-node", event.target.id);

and event.preventDefault() on my dragEnd event handler, but still the same.

Can someone help me out here?

Entire code is available at the codesandbox link I've pasted above.

EDIT: ON DRAG EVENT IS FIRING, BUT WITH THE FOLLOWING PROPERTIES SAME EVERYTIME

screenX: 0

screenY: 0

clientX: 0

clientY: 0

pageX: 0

pageY: 0

IS CAUSING THE ISSUE. WHY IS ALL THIS 0?

stackboy
  • 31
  • 3
  • Are you sure the `drag` event is not fired? It's fired for me, though the `clientX` is 0 and therefore doesn't pass an `if` condition. – Dan Macak Aug 10 '21 at 17:46
  • Hey @DanMacák you're right, the drag event IS firing but all the values (clientX clientY etc) are 0. How does one implement a slider in firefox then? There are so many sliders already in so many UI libraries... do you have any idea? – stackboy Aug 11 '21 at 01:18
  • My guess is that the libraries use a pointer based rather than drag based approach. Let me expand on this in an answer. – Dan Macak Aug 11 '21 at 06:37

2 Answers2

1

event.dataTransfer is irrelevant here, the actual problem is that Firefox doesn't track pointer position during drag events. To understand why, check this great answer to a problem similar to yours.

This means you can't use drag to update element's position based on the pointer which is dragging it. What you could use instead is dragover:

document.addEventListener('dragover', updateProgress)

Unlike drag, dragover tracks pointer position so you can use it to update the position of your slider. There is one gotcha though. On your page, there might be multiple draggable elements so you might want to check in your ondragover listener which one is being dragged. You can't easily do that though, since the document is the target of dragover, not the dragged element. So you also need to check which element is being dragged once dragstart is fired and maybe clean up the ondragover listener on dragend.

The alternative is to use Pointer events API, pointerdown, pointermove and pointerup in particular. The implementation effort is similar, but Pointer events should be more consistent across browsers (contrary to drag event) and devices, since Pointer events unifies many kinds of inputs - touch, mouse, pen - behind a single API.

Dan Macak
  • 16,109
  • 3
  • 26
  • 43
  • do you happen to have a good example which elaborates on Pointer events? I ran into issues with drag/drop as well but there is a lot you have to be aware of when trying to get rid of it.. – frans Apr 15 '22 at 17:12
0

You can fix this by having a somewhat global object that saves the current mouse position

    var mousePosition = {
        x: 0,
        y: 0,
    }

And update this with both the mousemove event and the dragover event. The mousemove event doesn't fire while dragging so we rely on the dragover event listener for the update since it has the event.clientY.

   document.addEventListener("mousemove", function (event) {
        mousePosition.x = event.clientX;
        mousePosition.y = event.clientY;
    });

   document.addEventListener("dragover", function (event) {
        mousePosition.x = event.clientX;
        mousePosition.y = event.clientY;
    })

So you could use the mousePosition object anywhere you need to get the mouse position