jQuery Drag and Drop on touch devices (iPad, Andro

2019-01-16 05:44发布

We have a card game website that makes extensive use of jQuery Draggable & Droppable and which has worked nearly flawlessly (when using a mouse) for almost a year.

We would REALLY like to have the site work on touch screen devices, but we cannot seem to get jQuery's drag and especially drop functionality to work reliably.

Dragging works "ok" unless the div being dragged is inside another dom element with any kind of offset, margin, padding, etc. If it is, the dragged element is also offset from the user's finger by a similar amount. May not sound like a big deal, but it makes the interface unusuable.

Dropping just doesn't seem to work.

We've researched various options presented here on SO (will try to update this post with links to some of them if I can), but none work for us.

We've also researched jQuery Mobile but this is still in alpha and even so seems to be more of a framework for making a site emulate the UI of a phone vs what we're looking for.

Most of the SO and Google posts on this topic seem to trail off in late 2010 which makes me think there is an obvious answer that maybe we're just missing.

BTW, the functionality we're looking for is clearly technically possible because the YUI libraries for drag and drop work as expected. Unfortunatly, we can't justtify refactoring the site to switch from jQuery to YUI.

Anyone out there have any ideas? We would settle for a answer that supports only iPad, but it really needs to not require we refactor the existing site.

Thanks!

8条回答
手持菜刀,她持情操
2楼-- · 2019-01-16 06:01

I suggest jQuery UI Touch Punch. I've tested it on iOS 5 and Android 2.3 and it works great on both.

查看更多
贪生不怕死
3楼-- · 2019-01-16 06:05

Given worked for me :

eventAfterRender: function (event, element, view ) {
         element.draggable();
},
查看更多
Rolldiameter
4楼-- · 2019-01-16 06:12

LikWidT has the simplest solution hands down from the website referenced. It would be great if any of the JQuery UI programmers could add this code or similar to their package. Jquery is certainly the simplest package to build drag/drop content for web developers... this is unfortunately a major flaw with nearly all devices having touch screens nowdays. I am now coding on a Surface Pro which is opening my eyes to these issues personally.

Just to reference the website again: https://github.com/furf/jquery-ui-touch-punch

Edit: Also to clarify how simple this fix is. I had to first ensure I re-ordered my include files such that JQuery Javascript file was first then Jquery UI Javascript then my CSS Files. Then I just copy/pasted below the include files the Javascript code in the post above and that was it. I modified no code it is simply a function that looks for any touches in real time and converts them to equivalent mouse actions. Hence my above assertions for JQuery coders.

查看更多
Rolldiameter
5楼-- · 2019-01-16 06:13

Old thread I know.......

Problem with the answer of @likwid_t is that it blocks also any input or other element that has to react on 'clicks' (for example inputs), so i wrote this solution. This solution made it possible to use any existing drag and drop library that is based upon mousedown, mousemove and mouseup events on any touch device (or cumputer). This is also a cross-browser solution.

I have tested in on several devices and it works fast (in combination with the drag and drop feature of ThreeDubMedia (see also http://threedubmedia.com/code/event/drag)). It is a jQuery solution so you can use it only with jQuery libs. I have used jQuery 1.5.1 for it because some newer functions don't work properly with IE9 and above (not tested with newer versions of jQuery).

Before you add any drag or drop operation to an event you have to call this function first:

simulateTouchEvents(<object>);

You can also block all components/children for input or to speed up event handling by using the following syntax:

simulateTouchEvents(<object>, true); // ignore events on childs

Here is the code i wrote. I used some nice tricks to speed up evaluating things (see code).

function simulateTouchEvents(oo,bIgnoreChilds)
{
 if( !$(oo)[0] )
  { return false; }

 if( !window.__touchTypes )
 {
   window.__touchTypes  = {touchstart:'mousedown',touchmove:'mousemove',touchend:'mouseup'};
   window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1};
 }

$(oo).bind('touchstart touchmove touchend', function(ev)
{
    var bSame = (ev.target == this);
    if( bIgnoreChilds && !bSame )
     { return; }

    var b = (!bSame && ev.target.__ajqmeclk), // Get if object is already tested or input type
        e = ev.originalEvent;
    if( b === true || !e.touches || e.touches.length > 1 || !window.__touchTypes[e.type]  )
     { return; } //allow multi-touch gestures to work

    var oEv = ( !bSame && typeof b != 'boolean')?$(ev.target).data('events'):false,
        b = (!bSame)?(ev.target.__ajqmeclk = oEv?(oEv['click'] || oEv['mousedown'] || oEv['mouseup'] || oEv['mousemove']):false ):false;

    if( b || window.__touchInputs[ev.target.tagName] )
     { return; } //allow default clicks to work (and on inputs)

    // https://developer.mozilla.org/en/DOM/event.initMouseEvent for API
    var touch = e.changedTouches[0], newEvent = document.createEvent("MouseEvent");
    newEvent.initMouseEvent(window.__touchTypes[e.type], true, true, window, 1,
            touch.screenX, touch.screenY,
            touch.clientX, touch.clientY, false,
            false, false, false, 0, null);

    touch.target.dispatchEvent(newEvent);
    e.preventDefault();
    ev.stopImmediatePropagation();
    ev.stopPropagation();
    ev.preventDefault();
});
 return true;
}; 

What it does: At first, it translates single touch events into mouse events. It checks if an event is caused by an element on/in the element that must be dragged around. If it is an input element like input, textarea etc, it skips the translation, or if a standard mouse event is attached to it it will also skip a translation.

Result: Every element on a draggable element is still working.

Happy coding, greetz, Erwin Haantjes

查看更多
我只想做你的唯一
6楼-- · 2019-01-16 06:15

Tested on HTC One M8 under Android 6.13 / samsung Galaxy tab S2

function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event

// restriction to preserve input use
    window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1};
    if( window.__touchInputs[event.target.tagName] ) return ;

} 
查看更多
我只想做你的唯一
7楼-- · 2019-01-16 06:18

I have created a jQuery plugin based on Erwinus' answer: https://github.com/RushPL/jquery.touch-mouse

查看更多
登录 后发表回答