RxJS Drag / Drop

Adapted from RsJS drag-drop example

by Lou Mauget

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.lite.js"></script>
<h4>RxJS  Drag and Drop Example</h4>
<div id="dragable"></div>
<p>Coordinated event streams facilitate drag and drop. Grab the misplaced fruit; move it; drop it. Life is good.</p>

CSS

body {
  font-family: "Arial", sans-serif
}

#dragable {
  background-image: url('https://openclipart.org/image/300px/svg_to_png/245506/orange-lineart.png&disposition=attachment');
  height: 70px;
  width: 70px;
  background-size: contain;
  position: absolute;
  cursor: move;
}

JavaScript

(function(dragable) {

  // Observe three major drag-drop events:
  // mousedown & mouseup on the dragable; mousemove over the document.
  var
  	mousedown = Rx.Observable.fromEvent(dragable, 'mousedown'),
    mousemove = Rx.Observable.fromEvent(document, 'mousemove'),
		mouseup   = Rx.Observable.fromEvent(dragable, 'mouseup');

  // A. Detect mouse down; 
  // B. While down, listen for mouse move and mouse up;
  // C. When mouse up: stop listening for moves and ups.
  var mousedrag = mousedown.flatMap( function( md ) {

    // Capture mouse down offset position
    var
    	startX = md.offsetX,
      startY = md.offsetY;

    // B1. Track mouse position differentials using mousemove until we hear a mouseup
    return mousemove.map( function( mm ) {
      mm.preventDefault();

      return {
        left: mm.clientX - startX,
        top: mm.clientY - startY
      };
      // C. stop the drag when mousup
    }).takeUntil(mouseup);
  })

  // Subscribe to mousemove's mousedrag stream:
  // B2. Update draggable's position from the mousedrag stream of events
  mousedrag.subscribe( function( pos ) {
    dragable.style.top = pos.top + 'px';
    dragable.style.left = pos.left + 'px';
  });

})($('#dragable').get(0));