Javascript Drag & Drop für Touch-Geräte [geschlossen]

120

Ich suche ein Drag & DROP-Plugin, das auf Touch-Geräten funktioniert.

Ich möchte ähnliche Funktionen wie das jQuery UI-Plugin, das "droppable" Elemente zulässt.

Das jqtouch-Plugin unterstützt das Ziehen, aber kein Ablegen.

Hier ist Drag & Drop, das nur iPhone / iPad unterstützt.

Kann mich jemand auf ein Drag & Drop-Plugin hinweisen, das auf Android / iOS funktioniert?

... oder es ist möglich, das jqtouch-Plugin auf Droppability zu aktualisieren, es läuft bereits auf Andriod und IOS.

Vielen Dank!

Joe
quelle
1
Dies ist in Bearbeitung, aber ich weiß nicht, welche Geräte es unterstützen: Diese plugins.jquery.com/project/mobiledraganddrop ... haben Sie die jQuerymobile.com-Bibliotheken durchgesehen? Ich fand auch diese doppelte SO-Frage: stackoverflow.com/questions/3172100/…
iivel
Vielen Dank. Ja, mobiledraganddrop unterstützt nur das Klicken und Ablegen auf Mobilgeräten. Ich konnte auf jQuerymobile.com nichts finden. Bei der anderen Frage ist die Antwort bereits als richtig markiert und bezieht sich auf sencha.com/products/touch, für das eine eingeschränkte Quelllizenz gilt .
Joe
Ich bin neugierig auf einen, der auf mobilen und Desktop-Browsern funktioniert.
Kalk

Antworten:

258

Sie können die Jquery-Benutzeroberfläche zum Ziehen und Ablegen mit einer zusätzlichen Bibliothek verwenden, die Mausereignisse in Berührung übersetzt. Dies ist die Bibliothek, die ich empfehle: https://github.com/furf/jquery-ui-touch-punch , with Dies sollte Ihr Drag & Drop von der Jquery-Benutzeroberfläche auf Touch-Geräten funktionieren

oder Sie können diesen Code verwenden, den ich verwende, er wandelt auch Mausereignisse in Berührungen um und funktioniert wie 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);
}

Und rufen Sie in Ihrem Dokument bereits die Funktion init () auf

Code von hier gefunden

Ryuutatsuo
quelle
11
Danke, auf meinem Android-Gerät ist das Zeug jetzt ziehbar. Das Klickereignis wird jedoch nicht mehr ausgelöst, wenn ich darauf klicke. Irgendwelche Ideen, wie man das behebt?
John Landheer
9
Hinweis: Da der Ereignis-Listener für das gesamte Dokument registriert ist, deaktiviert diese Lösung auch das Scrollen auf meinem Nexus S ...
Ethan Leroy
29
Vielen Dank für das Teilen. Sie sollten jedoch dem ursprünglichen Autor des von Ihnen veröffentlichten Codes eine Gutschrift geben. ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
undefiniert
2
@ JohnLandheer Ich habe das Problem behoben, indem ich die Ereignis-Listener nur an die Objekte angehängt habe, die ich document.getElementById('draggableContainer').addEventListener(...
ziehbar haben
1
Touch-Punch ist großartig. Eines dieser Dinge, bei denen es einfach funktioniert. Leider unterstützt es kein Dual-Touch ... was ich gerne sehen würde.
DA.
21

Für alle, die dies nutzen und die Klickfunktion beibehalten möchten (wie John Landheer in seinem Kommentar erwähnt), können Sie dies mit nur wenigen Änderungen tun:

Fügen Sie ein paar Globale hinzu:

var clickms = 100;
var lastTouchDown = -1;

Ändern Sie dann die switch-Anweisung vom Original in Folgendes:

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;
}

Vielleicht möchten Sie 'clickms' an Ihren Geschmack anpassen. Im Grunde ist es nur ein "Touchstart", gefolgt von einem "Touchend", um einen Klick zu simulieren.

EZ Hart
quelle
@EZ Hart - können Sie mir bitte mitteilen, wo Sie Ihren Code in den oben angegebenen Code einfügen müssen, um das Klickereignis zu aktivieren?
Valay
1
@ChakoDesai - Der Code in der Antwort wurde stark bearbeitet, seit ich meine Antwort geschrieben habe. Schauen Sie sich stackoverflow.com/posts/6362527/revisions an und sehen Sie sich den Code vom 30. Juni 2011 an. Meine Antwort wird aufgrund dieser Version viel sinnvoller sein.
EZ Hart
@EZ Hart - Ich habe meinen Code von der angegebenen URL aktualisiert. Aber warum clickfunktioniert das manchmal und manchmal nicht ???
Valay
@ChakoDesai - Ohne deinen Code zu sehen, kann ich nicht sicher sein. Vielleicht möchten Sie dafür eine neue Frage öffnen.
EZ Hart
Eine aktualisierte Antwort, damit der obige Code mit Klickereignissen
funktioniert
12

Danke für die obigen Codes! - Ich habe verschiedene Optionen ausprobiert und dies war das Ticket. Ich hatte Probleme damit, dass verhinderte, dass Default das Scrollen auf dem iPad verhinderte. Ich teste jetzt auf ziehbare Elemente und es funktioniert bisher hervorragend.

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}
gregpress
quelle
Haben Sie dies in Windows Phone getestet? Oder etwas anderes als iPhone? Aus früheren Erfahrungen scheint dies auf iPhones / iPads perfekt zu funktionieren, auf anderen Geräten, insbesondere auf Windows-Handys, jedoch nicht.
Fast ein Anfänger
10

Ich hatte die gleiche Lösung wie gregpress answer , aber meine ziehbaren Elemente verwendeten eine Klasse anstelle einer ID. Es scheint zu funktionieren.

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}
Eric
quelle
4
Die Tatsache, dass Sie einfach einen anderen Selektor verwendet haben, rechtfertigt keine separate Antwort, sondern Sie sollten die Antwort von @ gregpress kommentiert haben.
bPratik
2
@bPratik, es sei denn, er wollte die schönere Formatierung einer Antwort - und die Tatsache, dass er ein vollständiges Codebeispiel bereitgestellt hat, rechtfertigt eine separate Antwort. Hätte allerdings einen Kommentar hinterlassen sollen, der auf seine Antwort
verweist
8

Alter Thread, den ich kenne .......

Das Problem mit der Antwort von @ryuutatsuo ist, dass es auch alle Eingaben oder andere Elemente blockiert, die auf 'Klicks' reagieren müssen (zum Beispiel Eingaben), also habe ich diese Lösung geschrieben. Diese Lösung ermöglichte die Verwendung jeder vorhandenen Drag & Drop-Bibliothek, die auf Mousedown-, Mousemove- und Mouseup-Ereignissen auf jedem Touch-Gerät (oder Cumputer) basiert. Dies ist auch eine browserübergreifende Lösung.

Ich habe auf mehreren Geräten getestet und es funktioniert schnell (in Kombination mit der Drag & Drop-Funktion von ThreeDubMedia (siehe auch http://threedubmedia.com/code/event/drag )). Da es sich um eine jQuery-Lösung handelt, können Sie sie nur mit jQuery-Bibliotheken verwenden. Ich habe jQuery 1.5.1 dafür verwendet, da einige neuere Funktionen mit IE9 und höher nicht ordnungsgemäß funktionieren (nicht mit neueren Versionen von jQuery getestet).

Bevor Sie einem Ereignis eine Drag & Drop- Operation hinzufügen , müssen Sie zuerst diese Funktion aufrufen :

simulateTouchEvents(<object>);

Sie können auch alle Komponenten / untergeordneten Elemente für die Eingabe blockieren oder die Ereignisbehandlung beschleunigen, indem Sie die folgende Syntax verwenden:

simulateTouchEvents(<object>, true); // ignore events on childs

Hier ist der Code, den ich geschrieben habe. Ich habe ein paar nette Tricks benutzt, um die Bewertung zu beschleunigen (siehe 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;
}; 

Was es tut: Zuerst übersetzt es einzelne Berührungsereignisse in Mausereignisse. Es wird geprüft, ob ein Ereignis durch ein Element auf / in dem Element verursacht wird, das herumgezogen werden muss. Wenn es sich um ein Eingabeelement wie Eingabe, Textbereich usw. handelt, wird die Übersetzung übersprungen, oder wenn ein Standard-Mausereignis daran angehängt ist, wird auch eine Übersetzung übersprungen.

Ergebnis: Jedes Element in einem ziehbaren Element funktioniert noch.

Viel Spaß beim Codieren, Greetz, Erwin Haantjes

Codebeat
quelle
Welches Objekt soll ich übergeben simulateTouchEvents(<object>, true);?
Valay
Zum Beispiel: simulateTouchEvents ($ ('# yourid;), true); oder simulateTouchEvents (document.getElementById ('yourid'), true); etc
Codebeat
könnten Sie Blick auf meine andere Frage bitte Link ???
Valay
Verwenden Sie threedubmedia.com/code/event/drag und deaktivieren Sie die x- oder y-Bewegung des Elements. Wenn Sie den Code in diesem Artikel verwenden, können Sie die Bildlaufleisten "scrollen". Aber wissen Sie, warum Sie dies tun möchten, da eine Seite auf dem Mobiltelefon bereits Bildlaufleisten enthält. Verstehe nicht, was du damit machen willst. Erfolg!
Codebeat
Ich muss Drag-and-Drop von Spalten hinzufügen und beide scrollen. Wenn ich touchEreignisse einschalte chrome, kann ich nicht durch die Tabelle scrollen. Nicht einmal auf dem Handy.
Valay