114 votes

Comment faire en sorte qu'un div 'draggable()' de jQuery UI puisse glisser sur un écran tactile ?

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".

En gros, je clique ou je tapote sur div#everything (100% en hauteur et en largeur) qui écoute les clics, et une zone de saisie s'affiche. Vous ajoutez du texte, et lorsque vous avez terminé, il est enregistré. Vous pouvez faire glisser cet élément. Cela fonctionne sur les navigateurs normaux, mais sur un iPad avec lequel je peux faire des tests, je ne peux pas faire glisser les éléments. Si je touche pour sélectionner (l'image diminue alors légèrement), je ne peux pas la faire glisser. Il ne se déplace pas du tout vers la gauche ou la droite. I peut Je fais 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 la div d'entrée en une simple 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 pour les 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 STATE permet de sauvegarder les notes.

Onload, c'est le corps entier du 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>

Ma question est donc la suivante : comment faire pour que cela fonctionne mieux sur l'iPad ?

Je ne suis pas fixé sur jQuery UI, je me demande si c'est quelque chose que je fais mal avec jQuery UI, ou jQuery, ou s'il n'y a pas de meilleurs cadres pour faire des éléments draggables() compatibles avec les écrans tactiles.

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 !


UPDATE : J'ai pu simplement enchaîner ceci sur mon interface utilisateur jQuery. draggable() appelez et obtenez la draguabilité correcte sur l'iPad !

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

Le site Plugin jQuery Touch a fait l'affaire !

1 votes

Je suis curieux d'une chose : pouvez-vous faire glisser le div avec deux ou trois doigts ? Je sais qu'il faut parfois utiliser plusieurs doigts pour faire défiler du contenu intégré dans Safari mobile, il se peut donc que ce soit la même chose pour le contenu "glissant".

0 votes

Walter Mundt : merci ! Je n'ai pas essayé de variations de doigts, je vais essayer quand je l'aurai en main !

1 votes

Deux ou trois doigts empêchent en fait la "page entière" de défiler par inadvertance, mais n'apportent aucun changement pour les éléments mobiles.

143voto

ctrl-alt-dileep Points 1475

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

jquery-ui-touch-punch

Il traduit les événements de tapotement en é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 votes

Cette solution fonctionne très bien, une autre réponse que j'ai utilisée était boguée et n'a pas vraiment aidé.

0 votes

Une petite astuce : ça marche très bien, bien que si l'élément dragable est couvert de couches comme une image avec un masque au-dessus, le drag n'est pas activé mais la solution sera d'ajouter pointer-events:none ; sur les couches supérieures.

0 votes

Il s'agit d'une solution excellente et simple, il suffit d'utiliser le plugin et de continuer à travailler avec la fonction draggable de JQuery. Parfait, merci !

62voto

vonconrad Points 14378

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 .


En fonction de vos besoins, vous pouvez essayer l'option suivante plugin jQuery touch ; vous pouvez essayer un exemple ici . Il fonctionne bien pour glisser sur mon iPhone, alors que jQuery UI Draggable ne fonctionne pas.

Vous pouvez également essayer ce mais cela pourrait vous obliger à écrire votre propre fonction de dragging.

Note complémentaire : croyez-le ou non, nous entendons de plus en plus parler de la façon dont les appareils tactiles tels que l'iPad et l'iPhone posent des problèmes aux sites Web qui utilisent des fonctions :hover/onmouseover et du contenu glissant.

Si la solution sous-jacente vous intéresse, elle consiste à utiliser trois nouveaux événements JavaScript : ontouchstart, ontouchmove et ontouchend. Apple a d'ailleurs rédigé un article sur leur utilisation, que vous pouvez trouver à l'adresse suivante ici . Un exemple simplifié peut être trouvé ici . Ces événements sont utilisés dans les deux plugins dont je vous ai parlé.

2 votes

Super génial ! Tout ce que j'ai eu à faire, c'est d'enchaîner .touch({ animate: false, sticky: false, dragx: true, dragy: true, rotate: false, resort: true, scale: false }); à mon existant draggable() et cela fonctionne à merveille ! Je dois encore travailler sur tous les événements que je veux traiter pour obtenir le bon flux de travail, mais le plugin jQuery touch a fait l'affaire !

0 votes

Excellente première utilisation du système de primes. Merci ! Je vais aussi chercher d'autres façons de faire. J'espère que les gars de jQueryUI pourront intégrer le support de l'écran tactile. Cela semble être un ajout évident.

0 votes

Oui, je suis tout à fait d'accord que la prise en charge des écrans tactiles serait un bon ajout à jQuery UI. Heureux d'avoir pu vous aider !

24voto

Steve Points 231

Ce projet devrait être utile - il associe les événements tactiles aux événements de clics d'une manière qui permet à jQuery UI de fonctionner sur iPad et iPhone sans aucune modification. Il suffit d'ajouter le JS à tout projet existant.

http://code.google.com/p/jquery-ui-for-ipad-and-iphone/

7voto

thatmiddleway Points 1321

JQuery ui 1.9 va s'en charger pour vous. Voici une démo de l'application :

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

Il suffit de prendre le fichier jquery.mouse.ui.js, de le placer sous le fichier jQuery ui que vous chargez, et c'est tout ce que vous avez à faire ! Cela fonctionne aussi pour sortable.

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 votes

C'est génial qu'ils s'occupent de cette 1.9. Pour info, j'ai trouvé que la version du code dans cette démo comportait 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.

0 votes

J'ai mis à jour ma réponse pour répondre à cette question. Je n'ai pas encore obtenu d'erreurs dans mon cas d'utilisation avec l'original.

4voto

boulder_ruby Points 6257

Ce projet sur github peut être votre solution

https://github.com/furf/jquery-ui-touch-punch

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X