Javascript Glisser-déposer pour les appareils tactiles [fermé]

120

Je recherche un plugin drag & DROP qui fonctionne sur les appareils tactiles.

Je voudrais une fonctionnalité similaire au plugin jQuery UI qui autorise les éléments "droppables".

Le plugin jqtouch prend en charge le glisser-déposer, mais pas le drop.

Voici le glisser-déposer qui ne prend en charge que l'iPhone / iPad.

Quelqu'un peut-il me diriger vers un plugin glisser-déposer qui fonctionne sur Android / iOS?

... Ou il pourrait être possible de mettre à jour le plugin jqtouch pour la droppabilité, il fonctionne déjà sur Andriod et IOS.

Merci!

Joe
la source
1
Ceci est en cours, mais je ne sais pas quels appareils le prennent en charge: Ce plugins.jquery.com/project/mobiledraganddrop ... avez-vous parcouru les bibliothèques jQuerymobile.com? J'ai également trouvé cette question SO en double: stackoverflow.com/questions/3172100/…
iivel
Merci. Oui, mobiledraganddrop ne prend en charge que le click and drop sur les appareils mobiles. Je n'ai rien trouvé sur jQuerymobile.com. L'autre question a une réponse déjà marquée comme correcte qui fait référence à sencha.com/products/touch qui a une licence source limitée.
joe
Je suis curieux d'en connaître un qui fonctionne sur les navigateurs mobiles et de bureau.
Lime

Réponses:

258

Vous pouvez utiliser l'interface utilisateur Jquery pour le glisser-déposer avec une bibliothèque supplémentaire qui traduit les événements de la souris en tactile, ce dont vous avez besoin, la bibliothèque que je recommande est https://github.com/furf/jquery-ui-touch-punch , avec votre glisser-déposer depuis l'interface utilisateur de Jquery devrait fonctionner sur les appareils tactiles

ou vous pouvez utiliser ce code que j'utilise, il convertit également les événements de la souris en toucher et cela fonctionne comme par magie.

function touchHandler(event) {
    var touch = event.changedTouches[0];

    var simulatedEvent = document.createEvent("MouseEvent");
        simulatedEvent.initMouseEvent({
        touchstart: "mousedown",
        touchmove: "mousemove",
        touchend: "mouseup"
    }[event.type], true, true, window, 1,
        touch.screenX, touch.screenY,
        touch.clientX, touch.clientY, false,
        false, false, false, 0, null);

    touch.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
}

function init() {
    document.addEventListener("touchstart", touchHandler, true);
    document.addEventListener("touchmove", touchHandler, true);
    document.addEventListener("touchend", touchHandler, true);
    document.addEventListener("touchcancel", touchHandler, true);
}

Et dans votre document.ready appelez simplement la fonction init ()

code trouvé à partir d' ici

ryuutatsuo
la source
11
Merci, sur mon appareil Android, les éléments peuvent maintenant être déplacés. Cependant, l'événement de clic n'est plus déclenché lorsque je clique dessus. Des idées pour réparer celà?
John Landheer
9
Remarque: puisque l'écouteur d'événements est inscrit pour l'ensemble du document, cette solution désactive également le défilement sur mon Nexus S ...
Ethan Leroy
29
Merci d'avoir partagé ça. Cependant, vous devez donner crédit à l'auteur original du code que vous avez publié. ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
non défini
2
@JohnLandheer J'ai résolu le problème en attachant les écouteurs d'événements uniquement aux objets que je voulais faire glisser,document.getElementById('draggableContainer').addEventListener(...
chiliNUT
1
Touch-punch est génial. Une de ces choses «ça marche». Hélas, il ne prend pas en charge le double toucher ... ce que j'aimerais voir.
DA.
21

Pour tous ceux qui cherchent à utiliser cela et à conserver la fonctionnalité `` clic '' (comme John Landheer le mentionne dans son commentaire), vous pouvez le faire avec seulement quelques modifications:

Ajoutez quelques globaux:

var clickms = 100;
var lastTouchDown = -1;

Puis modifiez l'instruction switch de l'original à ceci:

var d = new Date();
switch(event.type)
{
    case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
    case "touchmove": type="mousemove"; lastTouchDown = -1; break;        
    case "touchend": if(lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms){lastTouchDown = -1; type="click"; break;} type="mouseup"; break;
    default: return;
}

Vous voudrez peut-être ajuster les «clics» à vos goûts. Fondamentalement, il suffit de regarder un «touchstart» suivi rapidement d'un «touchend» pour simuler un clic.

EZ Hart
la source
@EZ Hart - pourriez-vous s'il vous plaît me faire savoir où mettre votre code dans le code ci-dessus pour activer l'événement de clic ???
Valay
1
@ChakoDesai - Le code de la réponse a été fortement modifié depuis que j'ai écrit ma réponse. Consultez stackoverflow.com/posts/6362527/revisions et regardez le code du 30 juin 2011; ma réponse aura beaucoup plus de sens sur la base de cette version.
EZ Hart
@EZ Hart - J'ai mis à jour mon code à partir de l'url donnée. Mais pourquoi clickfonctionne parfois et parfois pas ???
Valay
@ChakoDesai - Sans voir votre code, je ne peux pas être sûr. Vous voudrez peut-être ouvrir une nouvelle question pour cela.
EZ Hart
Une réponse mise à jour pour faire fonctionner le code ci-dessus avec les événements de clic peut être trouvée ici: stackoverflow.com/questions/28218888/…
Blunderfest
12

Merci pour les codes ci-dessus! - J'ai essayé plusieurs options et c'était le ticket. J'ai eu des problèmes en ce que preventDefault empêchait le défilement sur l'ipad - je teste maintenant des éléments déplaçables et cela fonctionne très bien jusqu'à présent.

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}
Gregpress
la source
Avez-vous testé cela dans Windows Phone? Ou autre chose que l'iPhone? D'après l'expérience passée, cela semble fonctionner parfaitement sur les iPhones / iPads, mais ne fonctionne pas bien sur d'autres appareils, en particulier sur les téléphones Windows.
presque un débutant
10

J'avais la même solution que gregpress answer , mais mes éléments déplaçables utilisaient une classe au lieu d'un identifiant. Cela semble fonctionner.

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}
Eric
la source
4
Le fait que vous ayez simplement utilisé un sélecteur différent ne justifie pas d'être une réponse distincte, mais vous devriez plutôt avoir commenté la réponse de @ gregpress.
bPratik
2
@bPratik à moins qu'il ne veuille le meilleur formatage qu'une réponse offre - et le fait qu'il ait fourni un exemple de code entier justifie une réponse séparée. J'aurais dû laisser un commentaire
lié
8

Vieux fil je sais .......

Le problème avec la réponse de @ryuutatsuo est qu'il bloque également toute entrée ou autre élément qui doit réagir aux «clics» (par exemple les entrées), j'ai donc écrit cette solution. Cette solution a rendu possible l'utilisation de n'importe quelle bibliothèque de glisser-déposer existante basée sur des événements mousedown, mousemove et mouseup sur n'importe quel appareil tactile (ou cumputer). C'est également une solution multi-navigateurs.

J'ai testé sur 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 donc vous ne pouvez l'utiliser qu'avec les bibliothèques jQuery. J'ai utilisé jQuery 1.5.1 pour cela car certaines fonctions plus récentes ne fonctionnent pas correctement avec IE9 et les versions ultérieures (non testées avec les nouvelles versions de jQuery).

Avant d'ajouter une opération de glisser-déposer à un événement, vous devez d'abord appeler cette fonction :

simulateTouchEvents(<object>);

Vous pouvez également bloquer tous les composants / enfants pour l'entrée ou pour 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é de belles astuces pour accélérer l'évaluation des choses (voir 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;
}; 

Ce qu'il fait: Dans un premier temps, il convertit les événements d'une seule touche 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 comme input, textarea, etc., il ignore la traduction, ou si un événement de souris standard lui est attaché, il sautera également une traduction.

Résultat: chaque élément d'un élément déplaçable fonctionne toujours.

Bon codage, greetz, Erwin Haantjes

Codebeat
la source
quel objet dois-je passer simulateTouchEvents(<object>, true);???
Valay
Par exemple: simulateTouchEvents ($ ('# yourid;), true); ou simulateTouchEvents (document.getElementById ('yourid'), true); etc
Codebeat
pourriez-vous s'il vous plaît regarder mon autre lien de question ???
Valay
Utilisez threedubmedia.com/code/event/drag et désactivez le déplacement x ou y de l'élément. Lorsque vous utilisez le code de cet article, vous pouvez «faire défiler» les barres de défilement. Mais sachez pourquoi vous voulez faire cela, car une page sur un téléphone mobile a déjà des barres de défilement. Je ne comprends pas ce que vous voulez en faire. Succès!
Codebeat
Je dois ajouter un glisser-déposer de colonnes et faire défiler les deux. Lorsque j'active des touchévénements chrome, je ne peux pas faire défiler le tableau. Pas même sur mobile.
Valay