Nous avons un site Web de jeu de cartes qui utilise intensivement jQuery Draggable & Droppable et qui fonctionne presque sans faille (avec une souris) depuis presque un an.
Nous aimerions VRAIMENT que le site fonctionne sur des appareils à écran tactile, mais nous ne semblons pas pouvoir utiliser les fonctionnalités de glissement et de suppression de jQuery pour fonctionner de manière fiable.
Glisser fonctionne "ok" sauf si la div glissée se trouve à l'intérieur d'un autre élément dom avec n'importe quel type de décalage, marge, remplissage, etc. Si c'est le cas, l'élément glissé est également décalé du doigt de l'utilisateur d'une valeur similaire. Cela ne semble pas très grave, mais cela rend l'interface inutilisable.
Laisser tomber ne semble tout simplement pas fonctionner.
Nous avons recherché différentes options présentées ici sur SO (nous essayerons de mettre à jour ce post avec des liens vers certaines d’entre elles si je le peux), mais aucune ne fonctionne pour nous.
Nous avons également effectué des recherches sur jQuery Mobile, mais cela reste en alpha et semble néanmoins constituer un cadre permettant de faire en sorte qu'un site imite l'interface utilisateur d'un téléphone par rapport à ce que nous recherchons.
La plupart des SO et des publications de Google sur ce sujet semblent disparaître à la fin de 2010, ce qui me laisse penser qu'il est évident que nous sommes peut-être en train de nous manquer.
BTW, la fonctionnalité que nous recherchons est clairement techniquement possible car les bibliothèques YUI pour le glisser-déposer fonctionnent comme prévu. Malheureusement, nous ne pouvons pas nous contenter de refactoriser le site pour passer de jQuery à YUI.
Quelqu'un a une idée? Nous nous contenterions d'une réponse qui ne prend en charge que l'iPad, mais il ne faut vraiment pas demander à refactoriser le site existant.
Merci!
Collez ceci au début de votre fichier .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);
Appelez-moi le matin;) (c'est vraiment arrogant, je n'ai pas écrit cette solution, même si j'aimerais bien l'avoir, je le mentionnerais si je me souvenais de l'endroit où je l'avais trouvée, si quelqu'un savait d'où venait ce code, veuillez commenter et créditez cette personne)
UPDATE: Voilà: C'est ici que j'ai trouvé ceci
Je suggère jQuery UI Touch Punch . Je l'ai testé sur iOS 5 et Android 2.3 et cela fonctionne très bien sur les deux.
Vieux fil que je connais .......
Le problème avec la réponse de @likwid_t est qu’il bloque également toute entrée ou tout autre élément devant réagir sur des "clics" (par exemple des entrées), c’est pourquoi j’ai écrit cette solution. Cette solution a rendu possible l’utilisation de toute bibliothèque existante de glisser-déposer basée sur des événements mousedown, mousemove et mouseup sur n’importe quel périphérique tactile (ou cumputer). C'est aussi une solution multi-navigateur.
J'ai testé plusieurs appareils et cela fonctionne rapidement (en combinaison avec la fonction glisser-déposer de ThreeDubMedia (voir aussi http://threedubmedia.com/code/event/drag )). C'est une solution jQuery, vous ne pouvez donc l'utiliser qu'avec des bibliothèques jQuery. J'ai utilisé jQuery 1.5.1 car certaines fonctions plus récentes ne fonctionnent pas correctement avec IE9 et les versions ultérieures (non testées avec les versions plus récentes de jQuery).
Avant vous ajoutez une opération glisser-déposer à un événement vous devez d'abord appeler cette fonction:
simulateTouchEvents(<object>);
Vous pouvez également bloquer tous les composants/enfants pour la saisie ou accélérer la gestion des événements en utilisant la syntaxe suivante:
simulateTouchEvents(<object>, true); // ignore events on childs
Voici le code que j'ai écrit. J'ai utilisé quelques astuces de Nice pour accélérer l'évaluation (voir le code).
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;
};
Que fait-il: Au début, il traduit les événements tactiles en événements de souris. Il vérifie si un événement est causé par un élément sur/dans l'élément qui doit être déplacé. S'il s'agit d'un élément d'entrée tel que input, textarea, etc., la traduction est ignorée ou, si un événement de souris standard y est associé, une traduction est également ignorée.
Résultat: Chaque élément d'un élément déplaçable fonctionne toujours.
Bonne codage, greetz, Erwin Haantjes
J'ai créé un plugin jQuery basé sur la réponse d'Erwinus: https://github.com/RushPL/jquery.touch-mouse
LikWidT dispose de la solution la plus simple du site Web référencé. Ce serait formidable si l'un des programmeurs de l'interface utilisateur de JQuery pouvait ajouter ce code ou similaire à leur package. JQuery est certainement le paquet le plus simple pour créer du contenu par glisser/déposer pour les développeurs Web. C’est malheureusement un défaut majeur, presque tous les appareils ayant un écran tactile. Je suis en train de coder sur une Surface Pro, ce qui m’ouvre les yeux sur ces problèmes.
Juste pour référencer à nouveau le site: https://github.com/furf/jquery-ui-touch-punch
Edit: Également pour clarifier à quel point ce correctif est simple. Je devais d'abord m'assurer de re-commander mes fichiers d'inclusion de telle sorte que le fichier JQuery Javascript soit d'abord suivi de Jquery UI Javascript puis de mes fichiers CSS. Ensuite, je viens de copier/coller ci-dessous les fichiers include le code Javascript dans le post ci-dessus et c’est tout. Je n'ai modifié aucun code. Il s'agit simplement d'une fonction qui recherche toutes les retouches en temps réel et les convertit en actions équivalentes à la souris. D'où mes affirmations précédentes pour les codeurs JQuery.
Testé sur HTC One M8 sous 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 ;
}
Given a travaillé pour moi:
eventAfterRender: function (event, element, view ) {
element.draggable();
},
Vous pouvez essayer ce plugin mais semble fonctionner pour iphone, iPod et ipad. Je ne sais pas si ça résout ton problème. Peut être un spécifique ...
http://code.google.com/p/jquery-ui-for-ipad-and-iphone/
Mais Android cherche toujours une solution.
Faites-moi savoir si cela aide. Cordialement Ricardo Rodrigues