问题
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?
回答1:
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);
});
回答2:
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);
});
来源:https://stackoverflow.com/questions/9580574/combining-jquery-mobile-taphold-and-jquery-ui-draggable