8

Chcę mieć kilka klas draggables, każda odpowiadająca klasie droppables. Ale dodatkowo chcę mieć oddzielny "kosz na śmieci", w którym można przeciągnąć wszystkie elementy przeciągane, aż znajdzie się dla nich odpowiedni dropp.JQuery UI Drag/Droppable z wieloma zakresami?

Teraz można to łatwo osiągnąć za pomocą funkcji akceptacji. Jednak mogę mieć do 20 klas, każda z 30-40 draggables/droppables. Więc jeśli użyję do tego funkcji "zaakceptuj", w momencie, w którym wybiorę opcję przeciągania, mój chrome zamarza, ponieważ uruchamia testy dla każdego dropplay na ekranie :(

Można to rozwiązać, jeśli używam "zakresu" Właściwość, ponieważ wydaje się być w inny sposób.Jednakże, kiedy używam zakresu, nie wydaje się, aby wdrożyć koncepcję "kosz na śmieci", ponieważ może on mieć tylko jeden zakres!

Czy jest jakiś sposób omijać ten problem? Dać draggables więcej niż jeden zakres, lub dając bin bin wiele możliwości? Lub może jakieś inne rozwiązanie, którego nie mogę wymyślić?

+1

Witam. czy możesz opublikować jakiś kod, abyśmy mogli zobaczyć, co masz do tej pory? – chrisvillanueva

Odpowiedz

7

Wewnętrznie jQuery UI uruchomi następujący kod po uruchomieniu przeciągając znak draggable do d etermine które droppable s są uprawnione do otrzymania draggable.

var m = $.ui.ddmanager.droppables[t.options.scope] || []; 
var type = event ? event.type : null; // workaround for #2317 
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); 

droppablesLoop: for (var i = 0; i < m.length; i++) { 

    if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted 
    for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item 
    m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;         //If the element is not visible, continue 

    if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables 

    m[i].offset = m[i].element.offset(); 
    m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; 

} 

Jak widać kod nie jest trywialne i wyjaśniałoby, dlaczego widzisz Niska wydajność przy każdym uruchomieniu przeciąganie.

Warto zauważyć, że pierwszą rzeczą sprawdzoną pod numerem droppablesLoop jest to, czy droppable jest wyłączone.

Dlatego w celu zwiększenia wydajności zawsze można ręcznie wyłączyć odpowiednie widgety, które spowodują szybkie wyskoczenie z powyższego bloku kodu. Możesz to zrobić, używając zdarzenia start na urządzeniu draggable, które zostanie uruchomione jako pierwsze.

$('.draggable').draggable({ 
    start: function() { 
     $('.invalid-droppable-elements').droppable('option', 'disabled', true); 
    }, 
    stop: function() { 
     $('.invalid-droppable-elements').droppable('option', 'disabled', false); 
    } 
}); 

ten zasadniczo sprawia, że ​​wdrożenie accept/scope logikę siebie i wpływ na wydajność ma się do algorytmu. Jednak nie powinno być tak źle. Powodem, dla którego wtyczki są tak powolne, jest to, że muszą radzić sobie z wieloma różnymi sytuacjami.

jQuery UI nie obsługuje dodawania wielu zakresów do pojedynczych elementów draggable/droppable, ale można samodzielnie uruchomić tę funkcję.

Podam przykład razem, aby pokazać to tutaj - http://jsfiddle.net/tj_vantoll/TgQTP/1/.

+1

To rzeczywiście miało dobry wpływ na wydajność, ale nadal bardzo cienki w przeciwieństwie do używania zakresu ... Naprawdę miałem wszystkie droppables wyłączone z wyjątkiem bin i włączone tylko te, których potrzebuję. Czy nie ma sposobu, aby coś należało do więcej niż jednego zakresu? – Gilthans

+1

Edytowałem swoją odpowiedź, aby odpowiedzieć na Twoje pytanie. Krótka odpowiedź brzmi: nie jQuery UI nie obsługuje wielu zakresów, ale bardzo łatwo jest wdrożyć to na własną rękę. –

+0

To jest świetne, ale dla każdego, kto się zastanawia, wydaje się, że z ".each" jest trochę więcej "złożoności". Chyba że czegoś mi brakuje, możesz po prostu odwołać się do '$ ('. Przeciągalny')' i przenieść przypisanie 'var scope' do' start' – MCB