¿Cómo puedo hacer que un div jQuery UI 'draggable ()' se pueda arrastrar para la pantalla táctil?

112

Tengo una interfaz de usuario de jQuery draggable()que funciona en Firefox y Chrome. El concepto de interfaz de usuario consiste básicamente en hacer clic para crear un elemento de tipo "post-it".

Básicamente, hago clic o toco div#everything(100% alto y ancho) que escucha los clics y se muestra un área de texto de entrada. Agrega texto y luego, cuando termina, lo guarda. Puede arrastrar este elemento alrededor. Eso funciona en navegadores normales, pero en un iPad con el que puedo probar no puedo arrastrar los elementos. Si toco para seleccionar (luego se atenúa ligeramente), no puedo arrastrarlo. No se arrastrará a la izquierda ni a la derecha en absoluto. Yo puedo arrastrar hacia arriba o hacia abajo, pero no estoy arrastrando el individuo div, estoy arrastrando toda la página web.

Así que aquí está el código que utilizo para capturar 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);
});

Y aquí está el código que uso para "guardar" la nota y convertir el div de entrada en solo un div de visualización:

$('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();
    }
});

Y tengo este código cuando cargo la página de notas guardadas:

$('.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();
    }
});

Mi STATEobjeto se encarga de guardar las notas.

Onload, este es todo el cuerpo 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>

Entonces, mi pregunta es realmente: ¿cómo puedo hacer que esto funcione mejor en iPad?

No estoy configurado en jQuery UI, me pregunto si esto es algo que estoy haciendo mal con jQuery UI o jQuery, o si puede haber mejores marcos para hacer elementos draggable () compatibles con versiones anteriores o multiplataforma que lo harán funcionan para interfaces de usuario de pantalla táctil.

También serían bienvenidos comentarios más generales sobre cómo escribir componentes de interfaz de usuario como este.

¡Gracias!


ACTUALIZACIÓN: ¡ Pude simplemente encadenar esto en mi draggable()llamada jQuery UI y obtener la capacidad de arrastre correcta en iPad!

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

¡El complemento jQuery Touch funcionó!

artlung
fuente
1
Tengo curiosidad por algo: ¿puedes arrastrar el div con dos o tres dedos? Sé que a veces tienes que usar varios dedos para desplazarte por el contenido incrustado en Safari móvil, por lo que puede ser lo mismo para el contenido "arrastrable".
Walter Mundt
¡Gracias Walter Mundt! No he probado ninguna variación de dedos, ¡lo intentaré cuando lo tenga en mis manos!
artlung
1
en realidad, dos o tres dedos impidieron que la "página completa" se desplazara inadvertidamente, pero no modificaron la función de arrastrar.
artlung
Esta técnica no pareció funcionar para mí, desafortunadamente. :(
blaster
@blaster Deberá mirar algunas de las otras respuestas para otras posibles soluciones
artlung

Respuestas:

138

Después de perder muchas horas, ¡me encontré con esto!

jquery-ui-touch-punch

Traduce eventos de toque como eventos de clic. Recuerde cargar el script después de jquery.

Conseguí esto funcionando en el iPad y el iPhone

$('#movable').draggable({containment: "parent"});
ctrl-alt-dileep
fuente
2
Esta solución funciona muy bien, otra respuesta que me cansé fue con errores y realmente no ayudó
musefan
Un pequeño consejo: funciona muy bien, aunque si el elemento arrastrable cubierto con capas como una imagen con una máscara encima, no se activa el arrastre, pero la solución será agregar eventos de puntero: ninguno; en las capas superiores.
Adler
Esta es una solución excelente y simple, solo use el complemento y continúe trabajando con la función arrastrable de JQuery. ¡Perfecto gracias!
casi un principiante
Esto evitará elementos en los que se puede hacer clic dentro del archivo.
Abdul Sadik Yalcin
61

Precaución: esta respuesta se escribió en 2010 y la tecnología avanza rápidamente. Para obtener una solución más reciente, consulte la respuesta de @ ctrl-alt-dileep a continuación .


Dependiendo de sus necesidades, es posible que desee probar el complemento táctil jQuery ; puedes probar un ejemplo aquí . Funciona bien para arrastrar en mi iPhone, mientras que jQuery UI Draggable no lo hace.

Alternativamente, puede probar este complemento, aunque es posible que deba escribir su propia función arrastrable.

Como nota al margen: lo crea o no, estamos escuchando cada vez más rumores sobre cómo los dispositivos táctiles como el iPad y el iPhone están causando problemas a los sitios web que usan: funciones de desplazamiento / encendido del mouse y contenido arrastrable.

Si está interesado en la solución subyacente para esto, es utilizar tres nuevos eventos de JavaScript; ontouchstart, ontouchmove y ontouchend. Apple de hecho ha escrito un artículo sobre su uso, que puedes encontrar aquí . Puede encontrar un ejemplo simplificado aquí . Estos eventos se utilizan en los dos complementos a los que he vinculado.

vonconrad
fuente
2
¡Súper asombroso! ¡Todo lo que tenía que hacer era conectarme .touch({ animate: false, sticky: false, dragx: true, dragy: true, rotate: false, resort: true, scale: false });a mi draggable()llamada existente y funciona de maravilla! Todavía tengo que resolver todos los eventos con los que quiero lidiar para lograr el flujo de trabajo correcto, ¡pero el complemento jQuery touch funcionó!
artlung
4
el complemento ya no parece estar disponible en jquery.com. todavía puede encontrar el javascript aquí manifestinteractive.com/iphone/touch/js/jquery.touch.js
bjelli
1
Je, ahora el complemento también falta en manifestinteractive.com. Pruebe esto: plugins.jquery.com/files/jquery.touch.js.txt
Ian Hunter
5
esta respuesta ya no es válida. vea la respuesta de @ ctrl-alt-dileep a continuación (jquery-ui-touch-punch) para una respuesta de 2012
bjelli
1
@bjelli Gracias por señalar esto. Actualicé mi respuesta con una advertencia. :)
vonconrad
7

jQuery ui 1.9 se encargará de esto por usted. Aquí hay una demostración de la pre:

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

Simplemente tome jquery.mouse.ui.js, péguelo debajo del archivo jQuery ui que está cargando, ¡y eso es todo lo que debe hacer! Funciona también para ordenables.

Este código funciona muy bien para mí, pero si obtiene errores, puede encontrar una versión actualizada de jquery.mouse.ui.js aquí:

Jquery-ui sortable no funciona en dispositivos táctiles basados ​​en Android o IOS

ese camino
fuente
3
Es genial que estén lidiando con este 1.9. FWIW, encontré que la versión del código en esa demostración tenía errores y no funcionó tan bien. Alguien publicó una versión más correcta de esta pregunta: stackoverflow.com/questions/6745098/… que funciona mejor para mí.
asgeo1
Actualicé mi respuesta para abordar esto. Todavía no he recibido ningún error en mi caso de uso con el original.
thatmiddleway
1
El enlace de Dropbox no funciona.
BerggreenDK
2

Ayer estaba luchando con un problema similar. Ya tenía una solución "funcional" que usaba jQuery UI que se puede arrastrar junto con jQuery Touch Punch, que se mencionan en otras respuestas. Sin embargo, el uso de este método me estaba causando errores extraños en algunos dispositivos Android y, por lo tanto, decidí escribir un pequeño complemento de jQuery que puede hacer que los elementos HTML se puedan arrastrar mediante el uso de eventos táctiles en lugar de usar un método que emula eventos de mouse falsos.

El resultado de esto es jQuery Draggable Touch, que es un complemento de jQuery simple para hacer que los elementos se puedan arrastrar, que tiene dispositivos táctiles como su objetivo principal mediante el uso de eventos táctiles (como touchstart, touchmove, touchend, etc.). Todavía tiene un respaldo que usa eventos de mouse si el navegador / dispositivo no admite eventos táctiles.

Hey hombre
fuente
Hola Heyman, Qué buen trabajo. Gracias por compartirlo. ¿Funcionará también para jQuery redimensionable?
Haris
1

Puede intentar usar jquery.pep.js :

jquery.pep.js es un complemento ligero de jQuery que convierte cualquier elemento DOM en un objeto que se puede arrastrar. Funciona en la mayoría de los navegadores, desde el antiguo al nuevo, desde el tacto hasta el clic. Lo construí para satisfacer una necesidad en la que la función de arrastrar de jQuery UI no cumplía, ya que no funcionaba en dispositivos táctiles (sin algo de piratería).

Sitio web , enlace de GitHub

martynas
fuente
1
Gracias @martynas, ¡lo comprobaré!
artlung