Search code examples
javascriptjqueryjquery-uitouchdraggable

Draggable is blocking touch event


I'm attempting to use drag to move a div back and forth. This part works fine until the div has scrollable content. This isn't a problem on a desktop because of the scrollbar, but a problem occurs on touch devices. Because the touch event is conflicting with the drag event, I'm unable to scroll the content. I tried to create a condition to detect if the drag was more horizontal than vertical..

My hope was to prevent the dragging during a vertical touch interaction, but the UI drag method still fires and overrides the touch event. I'm using the touch-punch plugin to make the draggable work on touch devices, so maybe something in there has complicated the situation. It would be great if I could prevent the UI drag method from firing altogether until the horizontal drag condition is met. I think this would eliminate the interference.

// note the condition inside the drag function
      start: function(e){

        // get starting point of the drag
        startDragX = e.pageX;
        startDragY = e.pageY;
      },
      drag: function(e, ui){

        // prevent drag until user has moved 30px horizontally
        if (Math.abs(e.pageX - startDragX) < 30){
          ui.position.left = 0;
        } else {
          if (ui.position.left < 0) {

            // left drag
            ui.position.left = ui.position.left + 30;
          } else {
            // right drag
            ui.position.left = ui.position.left - 30;
          }
        }
      }

Here is a fiddle to demonstrate the problem (test on touch device): http://jsfiddle.net/jTMxS/2/


Solution

  • I had the exact same problem and after a lot of googling I found a solution in here:

    Drag & Drop on IPad Web App - while remaining Scroll functionality

    so have a look at the correct answer there and at the piece of code they mentioned (which is actually in other questions). I did remove the event.preventDefault() line because in my case I didn't want to lose the scrolling behavior. Hope this helps.

    EDIT I'll include here the details of my solution, as per Chris' comments. I replaced the touch punch plugin for these two functions:

    var init = function() {
        document.addEventListener('touchstart', handler, true);
        document.addEventListener('touchmove', handler, true);
        document.addEventListener('touchend', handler, true);
        document.addEventListener('touchcancel', handler, true);        
    };
    
    var handler = function(event) {
        var touch = event.changedTouches[0],
            simulatedEvent = document.createEvent('MouseEvent');
    
        simulatedEvent.initMouseEvent(
             { touchstart: 'mousedown', touchmove: 'mousemove', touchend: 'mouseup' } [event.type],
             true, true, window, 1, 
             touch.screenX, touch.screenY, touch.clientX, touch.clientY,
             false, false, false, false, 0, null);
    
        touch.target.dispatchEvent(simulatedEvent);
    };
    

    The init function needs to be called when the document ready.