support - jQuery Arrastrar y soltar en dispositivos táctiles(iPad, Android)
mobile drag (8)
Creé un plugin jQuery basado en la respuesta de Erwinus: https://github.com/RushPL/jquery.touch-mouse
Tenemos un sitio web de juegos de cartas que hace un uso extensivo de jQuery Draggable & Droppable y que ha funcionado casi sin problemas (cuando se usa un mouse) durante casi un año.
REALMENTE nos gustaría que el sitio funcione en dispositivos de pantalla táctil, pero parece que no podemos obtener el arrastre de jQuery y especialmente la funcionalidad de soltar para que funcione de manera confiable.
Arrastrar funciona "ok" a menos que el div que se arrastra esté dentro de otro elemento dom con cualquier tipo de desplazamiento, margen, relleno, etc. Si lo está, el elemento arrastrado también se desplazará del dedo del usuario en una cantidad similar. Puede que no parezca un gran problema, pero hace que la interfaz no sea útil.
Dejar caer simplemente no parece funcionar.
Hemos investigado varias opciones presentadas aquí en SO (intentaremos actualizar esta publicación con enlaces a algunas de ellas si puedo), pero ninguna funciona para nosotros.
También hemos investigado jQuery Mobile, pero todavía está en alfa e incluso parece ser un marco más para hacer que un sitio emule la interfaz de usuario de un teléfono frente a lo que estamos buscando.
La mayoría de las publicaciones de SO y Google sobre este tema parecen desaparecer a finales de 2010, lo que me hace pensar que hay una respuesta obvia que tal vez solo estamos perdiendo.
Por cierto, la funcionalidad que estamos buscando es claramente técnica porque las bibliotecas YUI para arrastrar y soltar funcionan como se espera. Desgraciadamente, no podemos justificar la refacturación del sitio para cambiar de jQuery a YUI.
¿Alguien tiene algunas ideas? Nos conformaríamos con una respuesta que solo sea compatible con iPad, pero realmente no es necesario que reordenemos el sitio existente.
¡Gracias!
LikWidT tiene la solución más simple desde el sitio web al que se hace referencia. Sería genial si cualquiera de los programadores de IU de JQuery pudiera agregar este código o similar a su paquete. Jquery es sin duda el paquete más simple para crear contenido de arrastrar / soltar para desarrolladores web ... Desafortunadamente, este es un gran error con casi todos los dispositivos que tienen pantallas táctiles hoy en día. Ahora estoy programando un Surface Pro que me está abriendo los ojos personalmente a estos problemas.
Solo para hacer referencia al sitio web de nuevo: https://github.com/furf/jquery-ui-touch-punch
Editar: También para aclarar qué tan simple es esta solución. Primero tuve que asegurarme de haber reordenado mis archivos de inclusión de modo que el archivo JQuery Javascript fuera primero, luego Jquery UI Javascript y luego mis archivos CSS. Luego copié / pegué debajo de los archivos de inclusión el código Javascript en la publicación de arriba y eso fue todo. Modifiqué ningún código, es simplemente una función que busca cualquier toque en tiempo real y los convierte en acciones de mouse equivalentes. De ahí mis afirmaciones anteriores para los codificadores de JQuery.
Pega esto al principio de tu archivo .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,
touchHandled;
function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event
// Ignore multi-touch events
if (event.originalEvent.touches.length > 1) {
return;
}
event.preventDefault(); //use this to prevent scrolling during ui use
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);
}
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;
// Simulate the mouseover event
simulateMouseEvent(event, ''mouseover'');
// Simulate the mousemove event
simulateMouseEvent(event, ''mousemove'');
// Simulate the mousedown event
simulateMouseEvent(event, ''mousedown'');
};
mouseProto._touchMove = function (event) {
// Ignore event if not handled
if (!touchHandled) {
return;
}
// Interaction was not a click
this._touchMoved = true;
// Simulate the mousemove event
simulateMouseEvent(event, ''mousemove'');
};
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;
};
mouseProto._mouseInit = function () {
var self = this;
// Delegate the touch handlers to the widget''s element
self.element
.on(''touchstart'', $.proxy(self, ''_touchStart''))
.on(''touchmove'', $.proxy(self, ''_touchMove''))
.on(''touchend'', $.proxy(self, ''_touchEnd''));
// Call the original $.ui.mouse init method
_mouseInit.call(self);
};
})(jQuery);
Llámame por la mañana;) (eso es realmente arrogante, no escribí esta solución aunque me gustaría haberlo hecho, lo mencionaría si recuerdo dónde lo encontré, si alguien sabe de dónde vino este código, por favor comenta y acreditar a esa persona)
ACTUALIZACIÓN: Aquí tienes: Aquí es donde encontré esto
Probado en HTC One M8 en Android 6.13 / samsung Galaxy tab S2
function simulateMouseEvent (event, simulatedType) { //use this function to simulate mouse event
// restriction to preserve input use
window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,''input'':1,''textarea'':1,''select'':1,''option'':1};
if( window.__touchInputs[event.target.tagName] ) return ;
}
Puede probar este complemento, pero parece funcionar para iphone, ipod y ipad. No estoy seguro si resuelve tu problema. Puede ser un específico ...
http://code.google.com/p/jquery-ui-for-ipad-and-iphone/
Pero Android todavía está buscando una solución.
Avíseme si ayuda. Saludos Ricardo Rodrigues
Sugiero jQuery UI Touch Punch . Lo probé en iOS 5 y Android 2.3 y funciona muy bien en ambos.
Viejo hilo que sé .......
El problema con la respuesta de @likwid_t es que bloquea también cualquier entrada u otro elemento que tiene que reaccionar en ''clics'' (por ejemplo, entradas), así que escribí esta solución. Esta solución hizo posible usar cualquier biblioteca existente de arrastrar y soltar que esté basada en eventos de mousedown, mousemove y mouseup en cualquier dispositivo táctil (o cumputer). Esta es también una solución de navegador cruzado.
He probado en varios dispositivos y funciona rápido (en combinación con la función de arrastrar y soltar de ThreeDubMedia (ver también http://threedubmedia.com/code/event/drag )). Es una solución de jQuery para que pueda usarla solo con jQuery libs. He utilizado jQuery 1.5.1 para ello porque algunas funciones más nuevas no funcionan correctamente con IE9 y superior (no probado con las versiones más recientes de jQuery).
Antes de agregar cualquier operación de arrastrar o soltar a un evento , primero debe llamar a esta función :
simulateTouchEvents(<object>);
También puede bloquear la entrada de todos los componentes / niños o acelerar el manejo de eventos usando la siguiente sintaxis:
simulateTouchEvents(<object>, true); // ignore events on childs
Aquí está el código que escribí. Utilicé algunos buenos trucos para acelerar la evaluación de las cosas (ver código).
function simulateTouchEvents(oo,bIgnoreChilds)
{
if( !$(oo)[0] )
{ return false; }
if( !window.__touchTypes )
{
window.__touchTypes = {touchstart:''mousedown'',touchmove:''mousemove'',touchend:''mouseup''};
window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,''input'':1,''textarea'':1,''select'':1,''option'':1};
}
$(oo).bind(''touchstart touchmove touchend'', function(ev)
{
var bSame = (ev.target == this);
if( bIgnoreChilds && !bSame )
{ return; }
var b = (!bSame && ev.target.__ajqmeclk), // Get if object is already tested or input type
e = ev.originalEvent;
if( b === true || !e.touches || e.touches.length > 1 || !window.__touchTypes[e.type] )
{ return; } //allow multi-touch gestures to work
var oEv = ( !bSame && typeof b != ''boolean'')?$(ev.target).data(''events''):false,
b = (!bSame)?(ev.target.__ajqmeclk = oEv?(oEv[''click''] || oEv[''mousedown''] || oEv[''mouseup''] || oEv[''mousemove'']):false ):false;
if( b || window.__touchInputs[ev.target.tagName] )
{ return; } //allow default clicks to work (and on inputs)
// https://developer.mozilla.org/en/DOM/event.initMouseEvent for API
var touch = e.changedTouches[0], newEvent = document.createEvent("MouseEvent");
newEvent.initMouseEvent(window.__touchTypes[e.type], true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
touch.target.dispatchEvent(newEvent);
e.preventDefault();
ev.stopImmediatePropagation();
ev.stopPropagation();
ev.preventDefault();
});
return true;
};
Lo que hace: Al principio, traduce eventos de un solo toque en eventos de mouse. Comprueba si un evento está causado por un elemento en / en el elemento que debe arrastrarse. Si se trata de un elemento de entrada como input, textarea, etc., omite la traducción, o si un evento de mouse estándar se adjunta también saltará una traducción.
Resultado: cada elemento en un elemento arrastrable sigue funcionando.
Happy coding, greetz, Erwin Haantjes
Dado funcionó para mí:
eventAfterRender: function (event, element, view ) {
element.draggable();
},