jquery-ui-touch-punch
jquery-ui-touch-punch copied to clipboard
Touch events doesn't works on Android 5.1.1
We've used this great library in one of our projects and now found that the click event doesn't work on Android 5.1.1 (lmy47v) on Nexus 10. Checked it also on the jquery-ui-touch-punch codepen demo here and encountered the same issue there. Click on draggable items doesn't work.
Guys, maybe you have some ideas what could be the reason and where to look for the reason?
Also come across this issue using jQuery 'sortable' as well, haven't found a fix as of yet though.
Does not work on Android 6.0.1, on HTC one M9. Same issue as ArMikael
Did you guys try out different smartphones and did it work on any of them? I noticed that timing really is crucial when it comes to the load order, especially making sure that JQuery UI actually is loaded before Touch Punch. Try putting them into the site's header to have a depending order here, when it works afterwards that should be the problem.
Here the same behavior. Works on desktop but not on Android Chrome and CM-Browser I have Android 5.1.1 on Galaxy S6 with Chrome 50.0.2661.89 CM 5.20.44
Hi,
I also had problem with some click event under Android and I think I found a fix for this. It seems to be related to a "false" mousemove event that prevent the click event to be launch in the touchEnd handler.
This is the fix :
...
var mouseProto = $.ui.mouse.prototype,
_mouseInit = mouseProto._mouseInit,
_mouseDestroy = mouseProto._mouseDestroy,
touchHandled, posX, posY
;
...
mouseProto._touchStart = function (event) {
... // Track movement to determine if interaction was a click self._touchMoved = false;
// Track element position to avoid "false" move
posX = event.originalEvent.changedTouches[0].screenX;
posY = event.originalEvent.changedTouches[0].screenY;
... }
mouseProto._touchMove = function (event) {
// Ignore event if not handled if (!touchHandled) { return; }
// Ignore if it's a "false" move (position not changed)
if ((posX==event.originalEvent.changedTouches[0].screenX) &&
(posY==event.originalEvent.changedTouches[0].screenY)) {
return;
}
...
};
Hope it helps !
This is almost the solution but for me this does not work precisely because there is no tolerance. The first saved posX is always a few pixels more/less than the screenX in the comparison.
This works for me:
// Track element position to avoid "false" move
posX = event.originalEvent.changedTouches[0].screenX.toFixed(0);
posY = event.originalEvent.changedTouches[0].screenY.toFixed(0);
// Ignore if it's a "false" move (position not changed)
var x = event.originalEvent.changedTouches[0].screenX.toFixed(0);
var y = event.originalEvent.changedTouches[0].screenY.toFixed(0);
// Ignore if it's a "false" move (position not changed)
if (Math.abs(posX - x) <= 2 && Math.abs(posY - y) <= 2) {
return;
}
Thanks @solution4you
Hi there, this works (pity) not on my IPad and IPhone6 (iOS)
can somebody please post the complete code wich works on all touchable devices? ( i will love you for solution!)
my code:
/*!
- jQuery UI Touch Punch 0.2.3 *
- Copyright 2011–2014, Dave Furfero
- Dual licensed under the MIT or GPL Version 2 licenses. *
- Depends:
- jquery.ui.widget.js
- jquery.ui.mouse.js */ (function ($) {
// Detect touch support $.support.touch = 'ontouchend' in document;
// Ignore browsers without touch support if (!$.support.touch) { return; }
var mouseProto = $.ui.mouse.prototype, _mouseInit = mouseProto._mouseInit, _mouseDestroy = mouseProto._mouseDestroy, touchHandled, posX, posY;
/**
-
Simulate a mouse event based on a corresponding touch event
-
@param {Object} event A touch event
-
@param {String} simulatedType The corresponding mouse event */ function simulateMouseEvent (event, simulatedType) {
// Ignore multi-touch events if (event.originalEvent.touches.length > 1) { return; }
event.preventDefault();
var touch = event.originalEvent.changedTouches[0], simulatedEvent = document.createEvent('MouseEvents');
// Initialize the simulated mouse event using the touch event's coordinates simulatedEvent.initMouseEvent( simulatedType, // type true, // bubbles
true, // cancelable
window, // view
1, // detail
touch.screenX, // screenX
touch.screenY, // screenY
touch.clientX, // clientX
touch.clientY, // clientY
false, // ctrlKey
false, // altKey
false, // shiftKey
false, // metaKey
0, // button
null // relatedTarget
);// Dispatch the simulated event to the target element event.target.dispatchEvent(simulatedEvent); }
/**
-
Handle the jQuery UI widget's touchstart events
-
@param {Object} event The widget element's touchstart event */ mouseProto._touchStart = function (event) {
var self = this;
// Ignore the event if another widget is already being handled if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) { return; }
// Set the flag to prevent other widgets from inheriting the touch event touchHandled = true;
// Track movement to determine if interaction was a click self._touchMoved = false;
// Track element position to avoid "false" move posX = event.originalEvent.changedTouches[0].screenX.toFixed(0); posY = event.originalEvent.changedTouches[0].screenY.toFixed(0);
// Simulate the mouseover event simulateMouseEvent(event, 'mouseover');
// Simulate the mousemove event simulateMouseEvent(event, 'mousemove');
// Simulate the mousedown event simulateMouseEvent(event, 'mousedown'); };
/**
-
Handle the jQuery UI widget's touchmove events
-
@param {Object} event The document's touchmove event */ mouseProto._touchMove = function (event) {
// Ignore event if not handled if (!touchHandled) { return; }
// Ignore if it's a "false" move (position not changed) var x = event.originalEvent.changedTouches[0].screenX.toFixed(0); var y = event.originalEvent.changedTouches[0].screenY.toFixed(0); // Ignore if it's a "false" move (position not changed) if (Math.abs(posX - x) <= 2 && Math.abs(posY - y) <= 2) { return; }
// Interaction was not a click
this._touchMoved = true;
// Simulate the mousemove event
simulateMouseEvent(event, 'mousemove');
};
/**
-
Handle the jQuery UI widget's touchend events
-
@param {Object} event The document's touchend event */ mouseProto._touchEnd = function (event) {
// Ignore event if not handled if (!touchHandled) { return; }
// Simulate the mouseup event simulateMouseEvent(event, 'mouseup');
// Simulate the mouseout event simulateMouseEvent(event, 'mouseout');
// If the touch interaction did not move, it should trigger a click if (!this._touchMoved) {
// Simulate the click event simulateMouseEvent(event, 'click');
}
// Unset the flag to allow other widgets to inherit the touch event touchHandled = false;
};
/**
-
A duck punch of the $.ui.mouse _mouseInit method to support touch events.
-
This method extends the widget with bound touch event handlers that
-
translate touch events to mouse events and pass them to the widget's
-
original mouse event handling methods. */ mouseProto._mouseInit = function () {
var self = this;
// Delegate the touch handlers to the widget's element self.element.bind({ touchstart: $.proxy(self, '_touchStart'), touchmove: $.proxy(self, '_touchMove'), touchend: $.proxy(self, '_touchEnd') });
// Call the original $.ui.mouse init method _mouseInit.call(self); };
/**
-
Remove the touch event handlers */ mouseProto._mouseDestroy = function () {
var self = this;
// Delegate the touch handlers to the widget's element self.element.unbind({ touchstart: $.proxy(self, '_touchStart'), touchmove: $.proxy(self, '_touchMove'), touchend: $.proxy(self, '_touchEnd') });
// Call the original $.ui.mouse destroy method _mouseDestroy.call(self); };
})(jQuery);
Put some alert or console commands to try to understand what happen with this._touchMoved The problem is related to the fact that the click event is not fired in the touchend event
// If the touch interaction did not move, it should trigger a click if (!this._touchMoved) {
// Simulate the click event simulateMouseEvent(event, 'click');
}
You have to understand why this part of code is not executed