8

Voglio avere diverse classi di draggable, ognuna corrispondente a una classe di droppable. Ma in aggiunta, voglio avere un "cestino dei rifiuti" separato, in cui tutti i draggables possono essere lasciati cadere fino a quando non si trova un droppable adatto per loro.Interfaccia utente JQuery Trascina/Droppable con più ambiti?

Ora, questo può essere facilmente ottenuto con una funzione di accettazione. Tuttavia, potrei avere fino a 20 classi, ognuna con 30-40 draggable/droppable. Quindi se uso una funzione "accetta" per questo, nel momento in cui raccolgo un trascinabile, il mio cromo si blocca mentre esegue test per ogni droppable sullo schermo :(

Questo può essere risolto se utilizzo lo 'scope' proprietà, dal momento che sembra che stia usando un modo diverso.Tuttavia, quando utilizzo un ambito, non riesco a implementare il concetto di "contenitore dei rifiuti", poiché può avere solo un ambito!

C'è qualche modo per bypassare questo problema? Dare ai draggable più di un ambito o dare al cestino molti ambiti? O forse un'altra soluzione a cui non riesco a pensare?

+1

ciao. puoi pubblicare del codice in modo che possiamo vedere quello che hai finora? – chrisvillanueva

risposta

7

Internamente jQuery UI eseguirà il seguente codice ogni volta che si avvia trascinamento di un draggable a d etermine che droppable s sono idonei a ricevere lo 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 }; 

} 

Come si può vedere il codice non è banale e spiegherebbe perché si sta vedendo un rallentamento delle prestazioni ogni volta che si avvia il trascinamento.

Una cosa da notare è che la prima cosa verificata nello droppablesLoop è se lo droppable è disabilitato.

Pertanto, per aumentare le prestazioni, è sempre possibile disabilitare manualmente i widget droppable appropriati che consentono di saltare rapidamente fuori dal blocco di codice in alto. È possibile farlo utilizzando l'evento start sullo draggable, che verrà attivato per primo.

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

Questo rende essenzialmente di implementare la logica accept/scope se stessi e l'impatto sulle prestazioni è fino al vostro algoritmo. Tuttavia, non dovrebbe essere così male da implementare. Il motivo per cui i plug-in sono così lenti è perché devono gestire molte situazioni diverse.

L'interfaccia utente jQuery non supporta l'aggiunta di più ambiti ai singoli elementi draggable/droppable ma è possibile ripristinarli autonomamente.

Ho messo un esempio insieme per mostrarlo qui - http://jsfiddle.net/tj_vantoll/TgQTP/1/.

+1

Questo ha avuto un buon effetto sulle prestazioni, ma ancora molto sottile rispetto all'utilizzo dell'ambito ... In realtà avevo disabilitato tutti i droppable tranne il bin e abilitato solo quelli che mi servivano. Non c'è modo di far sì che qualcosa appartenga a più di un ambito? – Gilthans

+1

Ho modificato la mia risposta per rispondere alla tua domanda. La risposta breve è no L'interfaccia utente di jQuery non supporta più ambiti ma è piuttosto facile da implementare da solo. –

+0

Questo è fantastico, ma per chiunque si chieda sembra che ci sia una "complessità" extra con '.each'. A meno che mi manchi qualcosa, puoi semplicemente fare riferimento a '$ ('. Draggable')' e spostare l'assegnazione di 'var scope' a' start' – MCB

Problemi correlati