// From http://www.redblobgames.com/
// Copyright 2017 Red Blob Games <redblobgames@gmail.com>
// License: Apache v2.0 <http://www.apache.org/licenses/LICENSE-2.0.html>

/** reference element: does not move during drag, defines coordinate system
    element: may move, gets mousedown handler
    handler: function called with (start, current, last)
    where last is the value returned last time handler called
    TODO: handle touch events -- http://devdocs.io/dom/touch_events/supporting_both_touchevent_and_mouseevent
*/
function makeDraggable(reference, element, handler) {
    element.addEventListener('mousedown', mouseDown);
    
    function coords(rect, e) {
        return {x: e.clientX - rect.left, y: e.clientY - rect.top};
    }

    function mouseDown(e) {
        if (e.button != 0) { return; /* don't trap right click */ }
        const rect = reference.getBoundingClientRect();
        const start = coords(rect, e);
        let last = handler(start, start, null);
        
        function mouseMove(e) {
            last = handler(start, coords(rect, e), last);
            e.preventDefault();
        }

        function mouseUp(e) {
            window.removeEventListener('mousemove', mouseMove);
            window.removeEventListener('mouseup', mouseUp);
            e.preventDefault();
        }

        window.addEventListener('mousemove', mouseMove);
        window.addEventListener('mouseup', mouseUp);
        e.preventDefault();
    }
}

@@ -408,118 +408,8 @@
 led%0A
-    TODO: handle touch events -- http://devdocs.io/dom/touch_events/supporting_both_touchevent_and_mouseevent%0A
 */%0Af
@@ -515,16 +515,181 @@
 eDown);%0A
+    element.addEventListener('touchstart', touchEvent);%0A    element.addEventListener('touchmove', touchEvent);%0A    element.addEventListener('touchend', touchEvent);%0A
     %0A   
@@ -1153,32 +1153,65 @@
 eventDefault();%0A
+            e.stopPropagation();%0A
         %7D%0A%0A     
@@ -1383,32 +1383,65 @@
 eventDefault();%0A
+            e.stopPropagation();%0A
         %7D%0A%0A     
@@ -1537,32 +1537,32 @@
 eup', mouseUp);%0A
-
         e.preven
@@ -1569,20 +1569,830 @@
 tDefault();%0A
+        e.stopPropagation();%0A    %7D%0A%0A    let touch_start = %5B%5D;%0A    let touch_last = %5B%5D;%0A    %0A    function touchEvent(e) %7B%0A        for (let i = 0; i %3C e.changedTouches.length; i++) %7B%0A            const rect = reference.getBoundingClientRect();%0A            const touch = e.changedTouches%5Bi%5D;%0A            let current = coords(rect, touch);%0A            if (e.type == 'touchstart') %7B%0A                touch_start%5Btouch.identifier%5D = current;%0A                touch_last%5Btouch.identifier%5D = handler(current, current, null);%0A            %7D else %7B%0A                let start = touch_start%5Btouch.identifier%5D;%0A                let last = touch_last%5Btouch.identifier%5D;%0A                touch_last%5Btouch.identifier%5D = handler(start, current, last);%0A            %7D%0A        %7D%0A        e.preventDefault();%0A        e.stopPropagation();%0A
     %7D%0A%7D%0A

Add touch and multitouch event handling