5

I'm having some problems while implementing jQuery Draggable http://jqueryui.com/demos/draggable/ on Android. I've created the html code and tested it using my browser. Then I compiled it on build.phonegap.com. After getting the .apk I installed it on my xperia x8 which is using Android 2.2 Froyo. The application ran well, but when I dragged the object it won't move.. Is there something wrong with my method? Thanks

Waynn Lue
  • 11,344
  • 8
  • 51
  • 76
justmyfreak
  • 1,260
  • 3
  • 16
  • 30
  • 1
    This plugin works perfectly for me (draggable and resizable): https://github.com/furf/jquery-ui-touch-punch. Demo here http://furf.com/exp/touch-punch/. The code works for BOTH regular browser and Android (iOS not tested) at the same time. – Calvin Jan 11 '12 at 21:08
  • @Calvin, This actually somehow works only on my Android phone. It does not work for me in Firefox on my computer. Very nice looking though on the phone – Earlz Feb 06 '12 at 17:36

6 Answers6

3

I use some script but forget where i take it:

 *
 * Copyright 2011, Dave Furfero
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Depends:
 *  jquery.ui.widget.js
 *  jquery.ui.mouse.js
 */
(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return;}var c=b.ui.mouse.prototype,e=c._mouseInit,a;function d(g,h){if(g.originalEvent.touches.length>1){return;}g.preventDefault();var i=g.originalEvent.changedTouches[0],f=document.createEvent("MouseEvents");f.initMouseEvent(h,true,true,window,1,i.screenX,i.screenY,i.clientX,i.clientY,false,false,false,false,0,null);g.target.dispatchEvent(f);}c._touchStart=function(g){var f=this;if(a||!f._mouseCapture(g.originalEvent.changedTouches[0])){return;}a=true;f._touchMoved=false;d(g,"mouseover");d(g,"mousemove");d(g,"mousedown");};c._touchMove=function(f){if(!a){return;}this._touchMoved=true;d(f,"mousemove");};c._touchEnd=function(f){if(!a){return;}d(f,"mouseup");d(f,"mouseout");if(!this._touchMoved){d(f,"click");}a=false;};c._mouseInit=function(){var f=this;f.element.bind("touchstart",b.proxy(f,"_touchStart")).bind("touchmove",b.proxy(f,"_touchMove")).bind("touchend",b.proxy(f,"_touchEnd"));e.call(f);};})(jQuery);

It work perfect with jquery-ui. U just need to add it to your html code like js library

3

This code maps touchstart, touchmove and touchend to their appropriate mouse events: There is still a bug with touchstart / mousedown, because the coordinates cannot be mapped directly.

My idea to fix this is to delay the mousedown dispatch until a touchmove occurs and then dispatch both mouse events with the coordinates of touchmove.

var mouseEventTypes = {
    touchstart : "mousedown",
    touchmove : "mousemove",
    touchend : "mouseup"
};

for (originalType in mouseEventTypes) {
    document.addEventListener(originalType, function(originalEvent) {
        event = document.createEvent("MouseEvents");
        touch = originalEvent.changedTouches[0];
        event.initMouseEvent(mouseEventTypes[originalEvent.type], true, true,
                window, 0, touch.screenX, touch.screenY, touch.clientX,
                touch.clientY, touch.ctrlKey, touch.altKey, touch.shiftKey,
                touch.metaKey, 0, null);
        originalEvent.target.dispatchEvent(event);
    });
}
Nappy
  • 3,016
  • 27
  • 39
  • Did you mean we need to fix the jquery mobile library? – justmyfreak May 31 '11 at 10:51
  • Have not tried jquery mobile yet. I tested this with normal `jquery.ui.Sortable` and `jquery.ui.Draggable`. But I do not use any external library, so it should work with other libraries, made for desktop usage aswell. – Nappy May 31 '11 at 13:03
  • No, I haven`t tried it out yet. Is it working by using jQuery Mobile? – justmyfreak Jun 01 '11 at 03:32
  • I do not see Drag & Drop featured in jQuery Mobile demos, so I do not assume that they have something like this currently. – Nappy Jun 01 '11 at 10:07
  • 1
    Nappy, does your code mentioned above work? If so can you possibly provide a more detailed example please. – jcrowson Oct 26 '11 at 16:33
  • Great.I have also same problem and above code works fine.Thanks u soo much – M007 Apr 18 '12 at 08:30
1

I used mixture of solutions above and realized that it helped with draggable elements, but it also made some elements in my project without ability to trigger click events on them, because the code above was preventing touchend events. I solved this problem. My version keeps draggable elements working and also keeps ability of other document elements to receive click events:

(function() {
function init() {
    var mouseEventTypes = {
        touchstart : "mousedown",
        touchmove : "mousemove",
        touchend : "mouseup"
    };

    for (originalType in mouseEventTypes) {
        document.addEventListener(originalType, function(originalEvent) {
            if(originalEvent.type == 'click')
                return;
            if (originalEvent.type != 'touchstart' && originalEvent.type !='touchend'){
                originalEvent.preventDefault();
            }
            event = document.createEvent("MouseEvents");
            touch = originalEvent.changedTouches[0];
            event.initMouseEvent(mouseEventTypes[originalEvent.type], true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, touch.ctrlKey, touch.altKey, touch.shiftKey, touch.metaKey, 0, null);
            originalEvent.target.dispatchEvent(event);
            event.preventDefault();         
        });
    }
}

init();
})();

Maybe it will help someone with similar issue. This problem with draggable elements occured only on my Galaxy Tab GT-P5110, Android version 4.0.4.

Andrej Lucansky
  • 725
  • 10
  • 17
1

To make clicks also work...

            var mouseEventTypes = {
                touchstart : "mousedown",
                touchmove : "mousemove",
                touchend : "mouseup",
                click : clickEvent
            };

            for(originalType in mouseEventTypes) {
                document.addEventListener(originalType, function(originalEvent) {
                    if (originalEvent.type != 'click' && originalEvent.type != 'touchstart')
                        originalEvent.preventDefault();
                    event = document.createEvent("MouseEvents");
                    touch = originalEvent.changedTouches[0];
                    event.initMouseEvent(mouseEventTypes[originalEvent.type], true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, touch.ctrlKey, touch.altKey, touch.shiftKey, touch.metaKey, 0, null);
                    originalEvent.target.dispatchEvent(event);
                    event.preventDefault();
                });
Bart
  • 94
  • 5
0

you can check out this question for a couple of suggestions and explanation of what is/isn't possible right now. It's my opinion that jQuery Mobile will probably have this as a possibility sooner or later.

Community
  • 1
  • 1
benpage
  • 4,418
  • 3
  • 41
  • 39
0

As an extension to Nappy's answer:

I have tried his code snippet on an app I am building for Android devices. It compiles fine and I am able to drag (in my case, a square) around, however the touchmove mouse event type only fires for 2 seconds and then stops.

This gives the impression that the object is not draggable, however on release, the object is moved to that location.

To fix this a simple one line of code is needed within the event listener:

    <script type="text/javascript" charset="utf-8">

    // Wait for PhoneGap to load
    //
    document.addEventListener("deviceready", onDeviceReady, false);

    // PhoneGap is ready
    //
    function onDeviceReady() {

    $(".shape").draggable();

    var mouseEventTypes = {
    touchstart : "mousedown",
    touchmove : "mousemove",
    touchend : "mouseup"
    };

for (originalType in mouseEventTypes) {
    document.addEventListener(originalType, function(originalEvent) {

originalEvent.preventDefault();

        event = document.createEvent("MouseEvents");
        touch = originalEvent.changedTouches[0];
        event.initMouseEvent(mouseEventTypes[originalEvent.type], true, true,
                window, 0, touch.screenX, touch.screenY, touch.clientX,
                touch.clientY, touch.ctrlKey, touch.altKey, touch.shiftKey,
                touch.metaKey, 0, null);
        originalEvent.target.dispatchEvent(event);
             event.preventDefault();

    });
}
    }

    </script>

The override of preventDefault fixes the issue with the mousedown handler not firing.

jcrowson
  • 4,290
  • 12
  • 54
  • 77