Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag 'n Drop example is broken #188

Closed
hbarcelos opened this issue Oct 2, 2018 · 2 comments · May be fixed by #189
Closed

Drag 'n Drop example is broken #188

hbarcelos opened this issue Oct 2, 2018 · 2 comments · May be fixed by #189

Comments

@hbarcelos
Copy link

I took the example code and modified it a little bit, using modern Javascript patterns:

const flyd = require('flyd');
const takeUntil = require('flyd/module/takeuntil');

function $(sel) {
  return document.querySelector(sel);
}

document.addEventListener('DOMContentLoaded', () => {
  const dragElm = $('#drag');

  const mouseDown = flyd.stream();
  const mouseMove = flyd.stream();
  const mouseUp = flyd.stream();

  dragElm.addEventListener('mousedown', mouseDown);
  document.addEventListener('mousemove', mouseMove);
  document.addEventListener('mouseup', mouseUp);

  const mouseDrag = flyd.chain(md => {
    const startX = md.offsetX;
    const startY = md.offsetY;

    console.log('Got mouse down!');
    console.log('Initial element position:', { startX, startY });

    return takeUntil(flyd.map(mm => {
      console.log('Got mouse move!');
      console.log('Current mouse position:', {
        x: mm.clientX,
        y: mm.clientY,
      });

      return {
        left: mm.clientX - startX,
        top: mm.clientY - startY,
      };
    }, mouseMove), mouseUp);
  }, mouseDown);

  flyd.on(({ top, left }) => {
    console.log('Current element position', { top, left });
    dragElm.style.top = `${top}px`;
    dragElm.style.left = `${left}px`;
  }, mouseDrag);
});

The behavior I can observe is that the drag 'n drop only works in the first drag. Then, I can no longer drag the box.

I added some logs to see what was going on and what I get is:

  • The mousemove event continues to be fired after the mouseup event happens (what I would expect, because it's bound to the document.
  • The on callback is executed only once.

I guessed I was doing something wrong, so I copy/pasted the example code, but the behavior was still the same.

What exactly is wrong here?

@nordfjord
Copy link
Collaborator

This has to do with takeUntil

const s1 = stream(1)
const s2 = stream(2)

const s3 = takeUntil(s1, s2)

s3().end() // true

The stream is immediately ended if s2 has a value

Internally in the switch-latest module we use

const dropCurrentValue = flyd.transduce(R.drop(1));

To drop 1 value from the stream to prevent this.

A more comprehensive fix is included in #175, but since the fix is not dependent on the rest of the changes in #175 I might just pop it out of there and make another PR for that.

The fix there is in the takeUntil module:

const dropCurrentValue = flyd.transduce(drop(1));
function takeUntil(src, term) {
  const end$ = flyd.merge(term.hasVal ? dropCurrentValue(term) : term, src.end);
  // ...
}

@hbarcelos
Copy link
Author

Thank's a lot @nordfjord. Will this PR be merged any time soon?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants