Seret dan lepas Javascript untuk perangkat sentuh [tertutup]

120

Saya mencari plugin drag & DROP yang berfungsi pada perangkat sentuh.

Saya ingin fungsionalitas yang mirip dengan plugin jQuery UI yang memungkinkan elemen "droppable".

The jqtouch Plugin mendukung menyeret, tetapi tidak ada menjatuhkan.

Berikut adalah drag & drop yang hanya mendukung iPhone / iPad.

Adakah yang bisa mengarahkan saya ke plugin seret & lepas yang berfungsi di android / ios?

... Atau mungkin juga untuk memperbarui plugin jqtouch untuk droppability, yang sudah berjalan di Android dan iOS.

Terima kasih!

joe
sumber
1
Ini sedang berlangsung, tetapi saya tidak tahu perangkat apa yang mendukungnya: plugins.jquery.com/project/mobiledraganddrop ini ... apakah Anda sudah melihat-lihat perpustakaan jQuerymobile.com? Saya juga menemukan pertanyaan SO duplikat ini: stackoverflow.com/questions/3172100/…
iivel
Terima kasih. Ya mobiledraganddrop hanya mendukung klik dan lepas pada perangkat seluler. Saya tidak dapat menemukan apa pun di jQuerymobile.com. Pertanyaan lain memiliki jawaban yang sudah ditandai sebagai benar yang merujuk ke sencha.com/products/touch yang memiliki lisensi sumber terbatas.
joe
Saya ingin tahu yang berfungsi di browser seluler dan desktop.
Kapur

Jawaban:

258

Anda dapat menggunakan UI Jquery untuk menyeret dan melepas dengan pustaka tambahan yang menerjemahkan kejadian mouse menjadi sentuhan yang Anda butuhkan, pustaka yang saya rekomendasikan adalah https://github.com/furf/jquery-ui-touch-punch , dengan ini seret dan lepas Anda dari Jquery UI harus bekerja pada perangkat sentuh

atau Anda dapat menggunakan kode ini yang saya gunakan, ini juga mengubah kejadian mouse menjadi sentuhan dan bekerja seperti sihir.

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

Dan di dokumen Anda, panggil saja fungsi init ()

kode ditemukan dari sini

ryuutatsuo
sumber
11
Terima kasih, di perangkat Android saya, barang-barang sekarang dapat diseret. Namun, peristiwa klik tidak diaktifkan lagi saat saya mengkliknya. Ada ide bagaimana memperbaikinya?
John Landheer
9
Catatan: Karena pendengar acara terdaftar untuk seluruh dokumen, solusi ini juga menonaktifkan pengguliran di Nexus S saya ...
Ethan Leroy
29
Terima kasih telah membagikan ini. Namun, Anda harus memberikan kredit kepada penulis asli dari kode yang Anda posting. ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
tidak ditentukan
2
@JohnLandheer Saya memperbaiki masalah ini dengan melampirkan event listener hanya ke objek yang saya ingin draggable,document.getElementById('draggableContainer').addEventListener(...
chiliNUT
1
Touch-punch bagus. Salah satu hal 'itu hanya berhasil'. Sayangnya, ini tidak mendukung dual-touch ... yang ingin saya lihat.
DA.
21

Bagi siapa pun yang ingin menggunakan ini dan mempertahankan fungsionalitas 'klik' (seperti yang disebutkan John Landheer dalam komentarnya), Anda dapat melakukannya hanya dengan beberapa modifikasi:

Tambahkan beberapa global:

var clickms = 100;
var lastTouchDown = -1;

Kemudian ubah pernyataan switch dari aslinya ke ini:

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

Anda mungkin ingin menyesuaikan 'clickm' dengan selera Anda. Pada dasarnya ini hanya menonton 'touchstart' diikuti dengan cepat oleh 'touchend' untuk mensimulasikan klik.

EZ Hart
sumber
@EZ Hart - dapatkah Anda memberi tahu saya di mana harus meletakkan kode Anda di atas kode yang diberikan untuk mengaktifkan peristiwa klik ???
Berlaku
1
@ChakoDesai - Kode dalam jawaban telah banyak diedit sejak saya menulis tanggapan saya. Lihat stackoverflow.com/posts/6362527/revised dan lihat kode dari 30 Juni 2011; jawaban saya akan jauh lebih masuk akal berdasarkan versi itu.
EZ Hart
@EZ Hart - Saya telah memperbarui kode saya dari url yang diberikan. Tapi kenapa terkadang clickberhasil dan terkadang tidak ???
Berlaku
@ChakoDesai - Tanpa melihat kode Anda, saya tidak yakin. Anda mungkin ingin membuka pertanyaan baru untuk itu.
EZ Hart
Jawaban yang diperbarui untuk membuat kode di atas berfungsi dengan peristiwa klik dapat ditemukan di sini: stackoverflow.com/questions/28218888/…
Blunderfest
12

Terima kasih untuk kode di atas! - Saya mencoba beberapa opsi dan ini tiketnya. Saya mengalami masalah dalam preventDefault yang mencegah pengguliran di ipad - Saya sekarang menguji item yang dapat diseret dan sejauh ini berfungsi dengan baik.

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}
gregpress
sumber
Sudahkah Anda menguji ini di Windows Phone? Atau apa pun selain iPhone? Dari pengalaman sebelumnya, ini tampaknya berfungsi sempurna di iPhone / iPad, tetapi tidak berfungsi dengan baik di perangkat lain, khususnya di Windows Phone.
hampir menjadi pemula
10

Saya memiliki solusi yang sama dengan jawaban gregpress , tetapi item yang dapat diseret saya menggunakan kelas, bukan id. Sepertinya berhasil.

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}
Eric
sumber
4
Fakta bahwa Anda baru saja menggunakan pemilih yang berbeda tidak menjamin menjadi jawaban yang terpisah, tetapi Anda seharusnya mengomentari jawaban @ gregpress.
bPratik
2
@bPratik kecuali dia menginginkan format yang lebih bagus dari jawaban yang diberikan - dan fakta bahwa dia memberikan seluruh contoh kode memang menjamin jawaban terpisah. Seharusnya meninggalkan komentar yang menghubungkan ke jawabannya meskipun ...
drzaus
8

Benang lama yang saya tahu .......

Masalah dengan jawaban @ryuutatsuo adalah bahwa ia juga memblokir input atau elemen lain yang harus bereaksi pada 'klik' (misalnya input), jadi saya menulis solusi ini. Solusi ini memungkinkan untuk menggunakan pustaka seret dan lepas yang ada yang didasarkan pada peristiwa mousedown, mousemove, dan mouseup pada perangkat sentuh apa pun (atau komputer). Ini juga merupakan solusi lintas-browser.

Saya telah mengujinya pada beberapa perangkat dan bekerja cepat (dikombinasikan dengan fitur drag and drop dari ThreeDubMedia (lihat juga http://threedubmedia.com/code/event/drag )). Ini adalah solusi jQuery sehingga Anda dapat menggunakannya hanya dengan jQuery libs. Saya telah menggunakan jQuery 1.5.1 untuk itu karena beberapa fungsi yang lebih baru tidak berfungsi dengan baik dengan IE9 dan di atasnya (tidak diuji dengan versi jQuery yang lebih baru).

Sebelum Anda menambahkan operasi seret atau lepas ke acara, Anda harus memanggil fungsi ini terlebih dahulu :

simulateTouchEvents(<object>);

Anda juga dapat memblokir semua komponen / turunan untuk input atau untuk mempercepat penanganan acara dengan menggunakan sintaks berikut:

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

Ini kode yang saya tulis. Saya menggunakan beberapa trik bagus untuk mempercepat evaluasi sesuatu (lihat kode).

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

Kegunaan: Awalnya, ini menerjemahkan peristiwa satu sentuhan menjadi peristiwa mouse. Ia memeriksa apakah suatu peristiwa disebabkan oleh elemen di / dalam elemen yang harus diseret. Jika itu adalah elemen input seperti input, textarea dll, itu melewatkan terjemahan, atau jika event mouse standar dilampirkan padanya itu juga akan melewatkan terjemahan.

Hasil: Setiap elemen pada elemen yang dapat diseret masih berfungsi.

Selamat membuat kode, salam, Erwin Haantjes

Codebeat
sumber
objek mana yang harus saya berikan simulateTouchEvents(<object>, true);???
Berlaku
Misalnya: simulateTouchEvents ($ ('# yourid;), true); atau simulateTouchEvents (document.getElementById ('yourid'), true); dll
Codebeat
bisakah Anda melihat tautan pertanyaan saya yang lain ???
Berlaku
Gunakan threedubmedia.com/code/event/drag dan nonaktifkan pemindahan elemen x atau y. Saat Anda menggunakan kode dalam artikel ini, Anda dapat 'menggulir' bilah gulir. Tetapi ketahuilah mengapa Anda ingin melakukan ini karena halaman di ponsel sudah memiliki scrollbar. Tidak mengerti apa yang ingin Anda lakukan dengannya. Keberhasilan!
Codebeat
Saya telah menambahkan drag-n-drop kolom dan menggulir keduanya. Saat saya mengaktifkan touchacara di chrome, saya tidak dapat menggulir tabel. Bahkan tidak di ponsel.
Berlaku