Comment puis-je rendre une div 'draggable ()' de l'interface utilisateur jQuery déplaçable pour l'écran tactile?


112

J'ai une interface utilisateur jQuery draggable()qui fonctionne dans Firefox et Chrome. Le concept de l'interface utilisateur consiste essentiellement à cliquer pour créer un élément de type «post-it».

Fondamentalement, je clique ou tape sur div#everything(100% haut et large) qui écoute les clics, et une zone de texte d'entrée s'affiche. Vous ajoutez du texte, puis lorsque vous avez terminé, il l'enregistre. Vous pouvez faire glisser cet élément. Cela fonctionne sur les navigateurs normaux, mais sur un iPad que je peux tester, je ne peux pas faire glisser les éléments. Si je touche pour sélectionner (il s'assombrit alors légèrement), je ne peux pas le faire glisser. Il ne traînera pas du tout à gauche ou à droite. Je peux faire glisser vers le haut ou vers le bas, mais je ne fais pas glisser l'individu div, je fais glisser toute la page Web.

Voici donc le code que j'utilise pour capturer les clics:

$('#everything').bind('click', function(e){
    var elem = document.createElement('DIV');
    STATE.top = e.pageY;
    STATE.left = e.pageX;
    var e = $(elem).css({
        top: STATE.top,
        left: STATE.left
    }).html('<textarea></textarea>')
    .addClass('instance')
    .bind('click', function(event){
        return false;
    });
    $(this).append(e);
});

Et voici le code que j'utilise pour "enregistrer" la note et transformer le div d'entrée en un div d'affichage:

$('textarea').live('mouseleave', function(){
    var val = jQuery.trim($(this).val());
    STATE.content = val;
    if (val == '') {
        $(this).parent().remove();
    } else {
        var div  = $(this).parent();
        div.text(val).css({
            height: '30px'
        });
        STATE.height = 30;
        if ( div.width() !== div[0].clientWidth || div.height () !== div[0].clientHeight ) {
            while (div.width() !== div[0].clientWidth || div.height () !== div[0].clientHeight) {
                var h = div.height() + 10;
                STATE.height = h;
                div.css({
                    height: (h) + 'px'
                });     // element just got scrollbars
            }
        }
        STATE.guid = uniqueID()
        div.addClass('savedNote').attr('id', STATE.guid).draggable({
            stop: function() {
                var offset = $(this).offset();
                STATE.guid = $(this).attr('id');
                STATE.top = offset.top;
                STATE.left = offset.left;
                STATE.content = $(this).text();
                STATE.height = $(this).height();
                STATE.save();
            }
        });
        STATE.save();
        $(this).remove();
    }
});

Et j'ai ce code lorsque je charge la page des notes enregistrées:

$('.savedNote').draggable({
    stop: function() {
        STATE.guid = $(this).attr('id');
        var offset = $(this).offset();
        STATE.top = offset.top;
        STATE.left = offset.left;
        STATE.content = $(this).text();
        STATE.height = $(this).height();
        STATE.save();
    }
});

Mon STATEobjet gère l'enregistrement des notes.

Onload, c'est tout le corps html:

<body> 
    <div id="everything"></div> 
<div class="instance savedNote" id="iddd1b0969-c634-8876-75a9-b274ff87186b" style="top:134px;left:715px;height:30px;">Whatever dude</div> 
<div class="instance savedNote" id="id8a129f06-7d0c-3cb3-9212-0f38a8445700" style="top:131px;left:347px;height:30px;">Appointment 11:45am</div> 
<div class="instance savedNote" id="ide92e3d13-afe8-79d7-bc03-818d4c7a471f" style="top:144px;left:65px;height:80px;">What do you think of a board where you can add writing as much as possible?</div> 
<div class="instance savedNote" id="idef7fe420-4c19-cfec-36b6-272f1e9b5df5" style="top:301px;left:534px;height:30px;">This was submitted</div> 
<div class="instance savedNote" id="id93b3b56f-5e23-1bd1-ddc1-9be41f1efb44" style="top:390px;left:217px;height:30px;">Hello world from iPad.</div> 

</body>

Donc, ma question est vraiment: comment puis-je améliorer ce travail sur iPad?

Je ne suis pas défini sur l'interface utilisateur jQuery, je me demande si c'est quelque chose que je fais mal avec l'interface utilisateur jQuery ou jQuery, ou s'il existe de meilleurs cadres pour créer des éléments draggable () multi-plateforme / rétrocompatibles qui fonctionne pour les interfaces utilisateur à écran tactile.

Des commentaires plus généraux sur la façon d'écrire des composants d'interface utilisateur comme celui-ci seraient également les bienvenus.

Merci!


MISE À JOUR: J'ai pu simplement enchaîner ceci sur mon draggable()appel d' interface utilisateur jQuery et obtenir la bonne draggability sur iPad!

.touch({
    animate: false,
    sticky: false,
    dragx: true,
    dragy: true,
    rotate: false,
    resort: true,
    scale: false
});

Le plugin jQuery Touch a fait l'affaire!


1
Je suis curieux de savoir quelque chose: pouvez-vous faire glisser le div avec deux ou trois doigts? Je sais que vous devez parfois utiliser plusieurs doigts pour faire défiler le contenu intégré dans Safari mobile, il peut donc en être de même pour le contenu «glissé».
Walter Mundt

Merci Walter Mundt! Je n'ai pas essayé de variations de doigts, j'essaierai quand je l'aurai entre les mains!
artlung

1
deux ou trois doigts ont en fait empêché la "page entière" de défiler par inadvertance, mais n'ont apporté aucun changement pour le déplaçable.
artlung

Cette technique ne semblait pas fonctionner pour moi, malheureusement. :(
blaster

@blaster Vous devrez regarder certaines des autres réponses pour d'autres solutions possibles
artlung

Réponses:


138

Après avoir perdu de nombreuses heures, je suis tombé sur ça!

jquery-ui-touch-punch

Il traduit les événements de tap comme des événements de clic. N'oubliez pas de charger le script après jquery.

Je l'ai fait fonctionner sur l'iPad et l'iPhone

$('#movable').draggable({containment: "parent"});

2
Cette solution fonctionne très bien, une autre réponse que j'ai fatiguée était un buggy et n'a vraiment pas aidé
musefan

Un petit conseil: fonctionne très bien, bien que si l'élément déplaçable recouvert de calques comme une image avec un masque au-dessus, aucun glissement n'est activé mais la solution sera l'ajout d'événements de pointeur: aucun; sur les couches supérieures.
Adler

C'est une solution formidable et simple, il vous suffit d'utiliser le plugin et de continuer à travailler avec la fonction déplaçable JQuery. Parfait merci!
presque un débutant

Cela empêchera les éléments cliquables dans le déplaçable.
Abdul Sadik Yalcin

61

Attention: cette réponse a été rédigée en 2010 et la technologie évolue rapidement. Pour une solution plus récente, voir la réponse de @ ctrl-alt-dileep ci-dessous .


Selon vos besoins, vous voudrez peut-être essayer le plugin jQuery touch ; vous pouvez essayer un exemple ici . Cela fonctionne bien pour faire glisser sur mon iPhone, contrairement à jQuery UI Draggable.

Alternativement, vous pouvez essayer ce plugin, bien que cela puisse vous obliger à écrire votre propre fonction déplaçable.

En guise de remarque: Croyez-le ou non, nous entendons un buzz croissant sur la façon dont les appareils tactiles tels que l'iPad et l'iPhone causent des problèmes à la fois aux sites Web utilisant: les fonctions de survol / à la souris et le contenu déplaçable.

Si vous êtes intéressé par la solution sous-jacente pour cela, utilisez trois nouveaux événements JavaScript; ontouchstart, ontouchmove et ontouchend. Apple a en fait écrit un article sur leur utilisation, que vous pouvez trouver ici . Un exemple simplifié peut être trouvé ici . Ces événements sont utilisés dans les deux plugins auxquels je suis lié.


2
Super génial! Tout ce que j'avais à faire était de chaîner .touch({ animate: false, sticky: false, dragx: true, dragy: true, rotate: false, resort: true, scale: false });mon draggable()appel existant et cela fonctionne un régal! Je dois encore travailler sur tous les événements que je veux gérer pour que le flux de travail soit correct, mais le plugin jQuery touch a fait l'affaire!
artlung

4
le plugin ne semble plus disponible sur jquery.com. vous pouvez toujours trouver le javascript ici manifestinteractive.com/iphone/touch/js/jquery.touch.js
bjelli

1
Heh, maintenant le plugin est également absent de manifestinteractive.com. Essayez ceci: plugins.jquery.com/files/jquery.touch.js.txt
Ian Hunter le

5
cette réponse n'est plus valable. voir la réponse de @ ctrl-alt-dileep ci-dessous (jquery-ui-touch-punch) pour une réponse 2012
bjelli

1
@bjelli Merci d'avoir signalé cela. J'ai mis à jour ma réponse avec un avertissement. :)
vonconrad


7

jQuery ui 1.9 s'en chargera pour vous. Voici une démo du pré:

https://dl.dropbox.com/u/3872624/lab/touch/index.html

Il suffit de récupérer le fichier jquery.mouse.ui.js, de le coller sous le fichier jQuery ui que vous chargez, et c'est tout ce que vous devriez faire! Fonctionne également pour triable.

Ce code fonctionne très bien pour moi, mais si vous obtenez des erreurs, une version mise à jour de jquery.mouse.ui.js peut être trouvée ici:

Jquery-ui sortable ne fonctionne pas sur les appareils tactiles basés sur Android ou IOS


3
C'est génial qu'ils traitent ce 1.9. FWIW, j'ai trouvé que la version du code de cette démo contenait des bogues et ne fonctionnait pas très bien. Quelqu'un a posté une version plus correcte sur cette question: stackoverflow.com/questions/6745098/… qui fonctionne mieux pour moi.
asgeo1

J'ai mis à jour ma réponse pour y remédier. Je n'ai pas encore eu d'erreur dans mon cas d'utilisation avec l'original.
thatmiddleway

1
Le lien Dropbox est en panne.
BerggreenDK


2

J'étais aux prises avec un problème similaire hier. J'avais déjà une solution "fonctionnelle" utilisant jQuery UI pouvant être déplacée avec jQuery Touch Punch, qui sont mentionnées dans d'autres réponses. Cependant, l'utilisation de cette méthode provoquait pour moi des bogues étranges dans certains appareils Android, et j'ai donc décidé d'écrire un petit plugin jQuery qui peut rendre les éléments HTML déplaçables en utilisant des événements tactiles au lieu d'utiliser une méthode qui émule de faux événements de souris.

Le résultat de ceci est jQuery Draggable Touch qui est un simple plugin jQuery pour rendre les éléments déplaçables, qui a des appareils tactiles comme cible principale en utilisant des événements tactiles (comme touchstart, touchmove, touchend, etc.). Il a toujours une solution de secours qui utilise les événements de souris si le navigateur / périphérique ne prend pas en charge les événements tactiles.


Salut Heyman, c'est du bon travail. Merci de l'avoir partagé. Cela fonctionnera-t-il aussi pour jQuery redimensionnable?
Haris

1

Vous pouvez essayer d'utiliser jquery.pep.js :

jquery.pep.js est un plugin jQuery léger qui transforme tout élément DOM en un objet déplaçable. Il fonctionne sur presque tous les navigateurs, de l'ancien au nouveau, du toucher au clic. Je l'ai construit pour répondre à un besoin dans lequel le draggable de jQuery UI ne répondait pas, car il ne fonctionnait pas sur les appareils tactiles (sans piratage).

Site Web , lien GitHub


1
Merci @martynas, je vais vérifier!
artlung
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.