justmyfreak
justmyfreak

Reputation: 1270

Draggable jQuery on Phonegap android

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

Upvotes: 5

Views: 10729

Answers (6)

user3111850
user3111850

Reputation: 83

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

Upvotes: 3

Andrej Lucansky
Andrej Lucansky

Reputation: 735

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.

Upvotes: 1

Bart
Bart

Reputation: 94

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();
                });

Upvotes: 1

jcrowson
jcrowson

Reputation: 4290

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.

Upvotes: 0

Nappy
Nappy

Reputation: 3046

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);
    });
}

Upvotes: 3

benpage
benpage

Reputation: 4618

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.

Upvotes: 0

Related Questions