質問

I'm working on a mobile application where I'm trying to combine jQuery UI's draggable functionality with jQuery Mobile's taphold event. The idea is that an element becomes draggable when a taphold is executed.

Draggable is being initialized on elements in the following code:

$('div.rect', '#outerBox').draggable({
    containment: "parent", 
    grid: [50, 50],
    disabled: true,
    stop: function(event, ui) {
        $(this).draggable('disable');
        $(this).removeClass('highlighted');
    }
}); 

As you can see the draggable functionality is disabled initially, because I want to enable it after a taphold event. To achieve this I'm currently using the following code:

// Bind long press event to rectangle elements
$('div.rect', '#outerBox').bind('taphold', function(event, ui) {
    // Enable dragging on long press
    $(this).addClass('highlighted');
    $(this).draggable('enable');
}); 

This works, but the problem is that a 'release-and-tap-again'-event is needed in order to drag the element around, instead of dragging directly after the taphold event. Could this be some kind of event-interference problem? I've tried things like event.preventDefault() but my knowledge of jQuery events isn't much so I have no idea whether or not this should make any difference.

Any idea on how to solve this one?

役に立ちましたか?

解決

First, jquery ui draggable does not work with touch events. I'm assuming you've made the nessesary adjustments to fix this.

I.e. see Jquery-ui sortable doesn't work on touch devices based on Android or IOS

Next I would say the touchstart event is not flowing through because of how taphold has been implemented in jquery mobile.

The draggable will only be initiated if it gets a touchstart/mousedown event.

I've seen something similar before, but with a doubletap in conjunction with a draggable.

You may need to manually trigger the touchstart event inside your taphold event handler for the draggable to kick in:

$('div.rect', '#outerBox').bind('taphold', function(event, ui) {
    var offset = $(this).offset();
    var type   = $.mobile.touchEnabled ? 'touchstart' : 'mousedown';
    var newevent = $.Event(type);
    newevent.which  = 1;
    newevent.target = this;
    newevent.pageX  = event.pageX ? event.pageX : offset.left;
    newevent.pageY  = event.pageY ? event.pageX : offset.top;

    $(this).trigger(newevent);
});

他のヒント

Though a little late - I got this to work by skipping the taphold plugin and using this instead. Remember to add Touch Punch!

$('#whatever').on('touchstart', function (event) {
    var me = this;

    if (!me.touching) {
        if (me.touched) { clearTimeout(me.touched); };
        me.touched = setTimeout(function () {
            //console.log('taphold');

            //Prevent context menu on mobile (IOS/ANDROID)
            event.preventDefault();

            //Enable draggable
            $this.draggable('enable');

            //Set internal flag
            me.touching = true;

            //Add optional styling for user
            $(me).addClass('is-marked');

            //trigger touchstart again to enable draggable through touch punch
            $(me).trigger(event);

            //Choose preferred duration for taphold
        }, 500);
    }
}).on('touchend', function () {
    //console.log('touchend');
    this.touching = false;

    //Disable draggable to enable default behaviour
    $(this).draggable('disable');

    //Remove optional styling
    $(this).removeClass('is-marked');

    clearTimeout(this.touched);
}).on('touchmove', function () {
    //console.log('touchmove');

    clearTimeout(this.touched);
});
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top