2011-08-19 9 views
11

Mam uporządkowaną listę filmów i przeciągalny zestaw filmów. Zasadniczo chcę się upewnić, że filmy przeciągnięte nie są w pierwszych 5 minutach filmu. Ponieważ długość filmu jest różna, chcę to sprawdzić podczas upuszczania - dodaj czas do tego czasu, a jeśli nie 5 minut, wróć i pokaż błąd.jQuery Draggable + Sortable - Jak odrzucić kroplę do sortowania?

Próbowałem podłączyć wszystkie wywołania zwrotne do przeciągania i sortowania (w tym nieudokumentowane wywołania zwrotne), aby wykonać mój test, ale cokolwiek próbuję, dom zawsze się zmienia (i wywołania sortowalne to jego wywołanie zwrotne aktualizacji) ...

Czy ktoś ma jakieś sugestie?

Odpowiedz

10

Można cofnąć operację przeciągania przez wywołanie metody cancel widgetu draggable (ta metoda jest nieudokumentowana, ale jego nazwisko nie zaczyna się od podkreślenia, co zapewne sprawia, że ​​„bezpieczniej” wiarygodnie używać). Działa to tylko podczas zdarzenia start, ponieważ inne zdarzenia pojawiają się zbyt późno, aby wywołać animację przywracania.

Jednak widget sortable będzie nadal zarejestrować spadek nawet jeśli operacja przeciągania jest anulowany, więc trzeba również usunąć nowo dodany element (podczas imprezy stop, jako zdarzenie start następuje zbyt wcześnie):

$("#yourSortable").sortable({ 
    start: function(event, ui) { 
     if (!canDropThatVideo(ui.item)) { 
      ui.sender.draggable("cancel"); 
     } 
    }, 
    stop: function(event, ui) { 
     if (!canDropThatVideo(ui.item)) { 
      ui.item.remove(); 
      // Show an error... 
     } 
    } 
}); 

Wyniki można zobaczyć w this fiddle (czwarta pozycja zawsze będzie odwracać).

Aktualizacja: Jako John Kurlak słusznie zwraca uwagę w komentarzach, przedmiot nie powróci ze względu na wezwanie do draggable("cancel"), ale ponieważ ui.sender jest null w naszym przypadku. Rzucanie czegokolwiek powoduje to samo zachowanie.

Niestety, wszystkie inne kombinacje próbowałem wynik w pozycji czym powrócił bez animacji miejsce, więc może nasz najlepiej jest unikać uzyskiwania dostępu ui.sender i zamiast napisać coś takiego:

start: function(event, ui) { 
    if (!canDropThatVideo(ui.item)) { 
     throw "cancel"; 
    } 
} 

przechwycony wyjątek nadal będzie wyświetlany w konsoli.

+0

Hej Dzięki za odpowiedź! Staram się jednak, aby to zadziałało - test (canDropThatVideo) musi znaleźć pozycję, którą upuszcza na listę, aby mógł porównać z sąsiednimi filmami. Próbowałem coś takiego: // pobierz sąsiednie vids var nextVid = $ (ui.item) .next(); var prevVid = $ (ui.item) .prev(); ale te dont wydają się uzyskać prawidłowe - prawdopodobnie dlatego, że jest na początku zdarzenia ... Czy to działa? – lopsided

+0

@ user612911, jest bardziej skomplikowany, ale może działać. Musisz połączyć się ze zdarzeniem 'sort' zamiast' start' i użyć odpowiednio 'ui.placeholder.next()' i 'ui.placeholder.prev()'. Prawdopodobnie będziesz także musiał pamiętać o decyzji, którą podjąłeś o przedmiocie (może z 'data()'), aby handler 'stop' wiedział, co robić. (Na marginesie, nie musisz wywoływać '$()' na członkach 'ui': są już obiektami jQuery.) –

+0

Wspaniale, mam to teraz działa dobrze.Dołączałem również pewną logikę do zdarzenia "start" przeciągania, aby dodać klasy "cantDropHere" do elementów, które nie są poprawnymi kroplami, a następnie wykluczyć te klasy z sortable. Dzięki! – lopsided

3

Znalazłem inny sposób. Jeśli nie przeszkadza ci nie mając animację to pływający z powrotem do jej pierwotnego miejsce zawsze można skorzystać z tej

.droppable({ 
    drop: function (event, ui) { 

     var canDrop = false; 

     //if you need more calculations for 
     //validation, like me, put them here 

     if (/*your validation here*/) 
      canDrop = true; 

     if (!canDrop) { 
      ui.draggable.remove(); 
     } 
     else{ 
      //you can put whatever else you need here 
      //in case you needed the drop anyway 
     } 
    } 
}).sortable({ 
    //your choice of sortable options 
}); 

użyłem tego bo potrzebne zdarzenie drop obu kierunkach.