Javascript Przeciągnij i upuść dla urządzeń dotykowych [zamknięte]

120

Szukam wtyczki drag & DROP działającej na urządzeniach dotykowych.

Chciałbym mieć podobną funkcjonalność do wtyczki jQuery UI, która pozwala na "upuszczanie" elementów.

Jqtouch wtyczki podpór przeciąganie, ale nie spada.

Oto przeciągnij i upuść, który obsługuje tylko iPhone / iPad.

Czy ktoś może wskazać mi kierunek wtyczki przeciągnij i upuść, która działa na Androidzie / iOS?

... Lub może być możliwe zaktualizowanie wtyczki jqtouch pod kątem możliwości upuszczania, działa już na Andriod i IOS.

Dzięki!

joe
źródło
1
To jest w toku, ale nie wiem, jakie urządzenia to obsługują: Ten plugins.jquery.com/project/mobiledraganddrop ... czy przeglądałeś biblioteki jQuerymobile.com? Znalazłem również to zduplikowane pytanie SO: stackoverflow.com/questions/3172100/ ...
iivel
Dzięki. Tak, mobiledraganddrop obsługuje tylko klikanie i upuszczanie na urządzeniach mobilnych. Nie mogłem znaleźć niczego na jQuerymobile.com. Drugie pytanie ma już oznaczoną odpowiedź jako poprawną, która odnosi się do sencha.com/products/touch, który ma ograniczoną licencję źródłową.
joe
Ciekawi mnie taki, który działa w przeglądarkach mobilnych i stacjonarnych.
Lime

Odpowiedzi:

258

Możesz użyć interfejsu użytkownika Jquery do przeciągania i upuszczania z dodatkową biblioteką, która tłumaczy zdarzenia myszy na dotyk, czego potrzebujesz, biblioteka, którą polecam to https://github.com/furf/jquery-ui-touch-punch , z to przeciąganie i upuszczanie z interfejsu Jquery powinno działać na urządzeniach dotykowych

lub możesz użyć tego kodu, którego używam, konwertuje on również zdarzenia myszy na dotyk i działa jak magia.

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

W swoim dokumencie już po prostu wywołaj funkcję init ()

kod znaleziony stąd

ryuutatsuo
źródło
11
Dzięki, na moim urządzeniu z Androidem można teraz przeciągać rzeczy. Jednak zdarzenie kliknięcia nie jest już uruchamiane, gdy je klikam. Jakieś pomysły, jak to naprawić?
John Landheer
9
Uwaga: Ponieważ odbiornik zdarzeń jest zarejestrowany dla całego dokumentu, to rozwiązanie wyłącza również przewijanie na moim Nexusie S ...
Ethan Leroy
29
Dzięki za udostępnienie tego. Należy jednak wskazać autora oryginalnego kodu, który opublikowałeś. ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
undefined
2
@JohnLandheer Naprawiłem problem, dołączając detektory wydarzenia tylko do obiektów, które chciałem przeciągnąć,document.getElementById('draggableContainer').addEventListener(...
chiliNUT
1
Dotyk jest świetny. Jedna z tych rzeczy „po prostu działa”. Niestety, nie obsługuje podwójnego dotyku ... co chciałbym zobaczyć.
DA.
21

Dla każdego, kto chce z tego skorzystać i zachować funkcję `` kliknięcia '' (jak wspomina John Landheer w swoim komentarzu), możesz to zrobić za pomocą zaledwie kilku modyfikacji:

Dodaj kilka globalnych:

var clickms = 100;
var lastTouchDown = -1;

Następnie zmień instrukcję switch z oryginalnej na następującą:

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

Możesz dostosować „kliknięcia” do swoich upodobań. Zasadniczo jest to po prostu obserwacja „touchstartu”, a następnie szybkiego „dotknięcia”, aby zasymulować kliknięcie.

EZ Hart
źródło
@EZ Hart - czy mógłbyś dać mi znać, gdzie umieścić kod w powyższym kodzie, aby włączyć zdarzenie kliknięcia ???
Valay,
1
@ChakoDesai - Kod w odpowiedzi był mocno edytowany, odkąd napisałem swoją odpowiedź. Sprawdź stackoverflow.com/posts/6362527/revisions i spójrz na kod z 30 czerwca 2011; moja odpowiedź będzie miała dużo więcej sensu w oparciu o tę wersję.
EZ Hart
@EZ Hart - Zaktualizowałem swój kod z podanego adresu URL. Ale dlaczego czasami clickdziała, a czasami nie ???
Valay
@ChakoDesai - Nie widząc twojego kodu, nie mam pewności. Możesz otworzyć nowe pytanie.
EZ Hart
Zaktualizowaną odpowiedź, aby powyższy kod działał ze zdarzeniami kliknięć, można znaleźć tutaj: stackoverflow.com/questions/28218888/…
Blunderfest
12

Dzięki za powyższe kody! - Wypróbowałem kilka opcji i to był bilet. Miałem problemy z tym, że disableDefault uniemożliwiało przewijanie na iPadzie - testuję teraz elementy do przeciągania i na razie działa świetnie.

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}
gregpress
źródło
Czy przetestowałeś to w Windows Phone? Albo coś innego niż iPhone? Z wcześniejszych doświadczeń wydaje się, że działa to idealnie na iPhone'ach / iPadach, ale nie działa dobrze na innych urządzeniach, szczególnie w telefonach z systemem Windows.
prawie początkujący
10

Miałem to samo rozwiązanie, co odpowiedź gregpress , ale moje elementy do przeciągania używały klasy zamiast identyfikatora. Wydaje się, że działa.

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}
Eric
źródło
4
Fakt, że po prostu użyłeś innego selektora, nie uzasadnia bycia oddzielną odpowiedzią, ale zamiast tego powinieneś skomentować odpowiedź @ gregpress.
bPratik,
2
@bPratik, chyba że chciał, aby odpowiedź była ładniejsza - a fakt, że dostarczył cały przykład kodu, gwarantuje oddzielną odpowiedź. Powinienem jednak zostawić komentarz z linkiem do jego odpowiedzi ...
drzaus
8

Stary wątek, który znam .......

Problem z odpowiedzią @ryuutatsuo polega na tym, że blokuje on również wszelkie dane wejściowe lub inny element, który ma reagować na „kliknięcia” (na przykład wejścia), więc napisałem to rozwiązanie. To rozwiązanie umożliwiło użycie dowolnej istniejącej biblioteki przeciągnij i upuść opartej na zdarzeniach mousedown, mousemove i mouseup na dowolnym urządzeniu dotykowym (lub komputerze). Jest to również rozwiązanie dla różnych przeglądarek.

Przetestowałem na kilku urządzeniach i działa szybko (w połączeniu z funkcją przeciągnij i upuść w ThreeDubMedia (patrz także http://threedubmedia.com/code/event/drag )). Jest to rozwiązanie jQuery, więc możesz go używać tylko z bibliotekami jQuery. Użyłem do tego jQuery 1.5.1 , ponieważ niektóre nowsze funkcje nie działają poprawnie z IE9 i nowszymi (nie testowane z nowszymi wersjami jQuery).

Przed dodaniem operacji przeciągnij lub upuść do zdarzenia musisz najpierw wywołać tę funkcję :

simulateTouchEvents(<object>);

Możesz również zablokować wszystkie składniki / elementy podrzędne na potrzeby wprowadzania danych lub przyspieszyć obsługę zdarzeń, używając następującej składni:

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

Oto kod, który napisałem. Użyłem kilku fajnych sztuczek, aby przyspieszyć ocenę rzeczy (patrz kod).

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

Co robi: Na początku tłumaczy zdarzenia pojedynczego dotknięcia na zdarzenia myszy. Sprawdza, czy zdarzenie jest spowodowane przez element znajdujący się na / w elemencie, który należy przeciągać. Jeśli jest to element wejściowy, taki jak input, textarea itp., Pomija tłumaczenie lub jeśli jest do niego dołączone standardowe zdarzenie myszy, również pomija tłumaczenie.

Wynik: każdy element elementu, który można przeciągać, nadal działa.

Miłego kodowania, pozdrawiam, Erwin Haantjes

Codebeat
źródło
który obiekt powinienem podać simulateTouchEvents(<object>, true);???
Valay,
Na przykład: simulateTouchEvents ($ ('# yourid;), true); lub simulateTouchEvents (document.getElementById ('yourid'), true); itd.
Codebeat
czy mógłbyś spojrzeć na moje inne łącze do pytania ???
Valay
Użyj threedubmedia.com/code/event/drag i wyłącz przesuwanie elementu x lub y. Używając kodu z tego artykułu, możesz „przewijać” paski przewijania. Ale wiedz, dlaczego chcesz to zrobić, ponieważ strona w telefonie komórkowym ma już paski przewijania. Nie rozumiem, co chcesz z tym zrobić. Sukces!
Codebeat
Muszę dodać przeciągnij i upuść kolumny i przewijanie obu. Po włączeniu touchwydarzeń w programie chromenie mogę przewijać tabeli. Nawet na telefonie komórkowym.
Valay