Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining jQuery Mobile taphold and jQuery UI draggable

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?

like image 217
Thomas Avatar asked Mar 06 '12 09:03

Thomas


People also ask

What is draggable option in jQuery Mobile?

jQuery Mobile is a web-based technology that can be used to make responsive content for websites that can be accessed on all types of smartphones, tablets, and desktops. In this article, we are going to learn the jQuery Mobile Draggable option () method. Using this method, we can get, set or update any parameter’s value of the Draggable widget.

How to drag and drop an object using jQuery?

This because these three libraries permit ignoring all the complexity of a drag and drop operation, just by calling one method: $.draggable () that informs the jQuery subsystem that an object can be dragged. The $.draggable method can be decorated with drop: function (event,ui) {} parameter in which we can add the code for handling the drop event.

What is droppable method in jQuery UI?

Droppable () Method: This method allows the elements to be dropped with the help of mouse. Using jQuery UI, we can make the DOM (D ocument O bject M odel) elements to drop anywhere within the view port on the specified target. This can be done by clicking on the draggable object by mouse and drop it on the specified target.

What are the best libraries for drag and drop in jQuery?

jQuery, jQuery-ui and touch-pouch library can be considered the standard de facto for drag and drop operations in desktop and mobile browser. This because these three libraries permit ignoring all the complexity of a drag and drop operation, just by calling one method: $.draggable() that informs the jQuery subsystem that an object can be dragged.


2 Answers

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);
});
like image 108
asgeo1 Avatar answered Oct 11 '22 09:10

asgeo1


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);
});
like image 22
Godsayah Avatar answered Oct 11 '22 10:10

Godsayah