2009-11-26 18 views
41

Ho un'applicazione con una lunga lista che cambia frequentemente, e ho bisogno che gli elementi di quella lista siano trascinabili.jQuery Drag & Drop utilizzando eventi dal vivo

Ho utilizzato il plugin trascinabile dell'interfaccia utente jQuery, ma è lento aggiungere a più di 400 voci di elenco e deve essere aggiunto nuovamente ogni volta che vengono aggiunti nuovi elementi di elenco.

Qualcuno sa di un plug-in simile al plugin trascinabile dell'interfaccia utente jQuery che utilizza gli eventi .live() di jQuery 1.3? Questo risolverebbe entrambi i problemi.

+0

Che cosa significa se {jQuery (questo) .data ' ("init", vero);} 'do? –

risposta

44

La soluzione di Wojtek ha funzionato perfettamente per me. Finii per cambiare un po 'po' per renderlo estendere jQuery ...

(function ($) { 
    $.fn.liveDraggable = function (opts) { 
     this.live("mouseover", function() { 
     if (!$(this).data("init")) { 
      $(this).data("init", true).draggable(opts); 
     } 
     }); 
     return this; 
    }; 
}(jQuery)); 

Ora, invece di chiamare le cose come:

$(selector).draggable({opts}); 

... basta usare:

$(selector).liveDraggable({opts}) 
+0

Questo mi ha rotto del tutto. Hai bisogno di metterlo da qualche parte in particolare per estendere la funzionalità JQuery? – Andrew

+1

Devi dichiararlo dopo aver caricato jQuery e prima di usarlo nel tuo codice. Che errore stai ottenendo? – stldoug

+0

Grazie fantastici! – Chris

10

Si potrebbe fare funzione wrapper in questo modo:

function liveDraggable(selector, options){ 
    jQuery(selector).live("mouseover",function(){ 
    if (!jQuery(this).data("init")) { 
     jQuery(this).data("init", true); 
     jQuery(this).draggable(options); 
    } 
    }); 
} 

(io uso prototipo con jQuery - è per questo che ho messo jQuery() invece di $())

E ora invece di $ (selettore) .draggable ({opts}) usa liveDraggable (selettore, {opts})

+0

Questo ha funzionato perfettamente per me, grazie. – Wil

21

Questo è un esempio di codice che ha funzionato perfettamente per me

$('.gadgets-column').live('mouseover',function(){ 
    $(this).draggable(); 
}); 
+0

ha funzionato come un incantesimo per me, grazie – Raz

+0

+1 è la soluzione più semplice. – enloz

+3

è una soluzione semplice, ma trascinabile viene eseguito su tutti gli elementi DOM con gadget-column di classe * ogni volta * si passa sopra uno di essi ... –

7

Il codice di Stldoug ha funzionato per me, ma non è necessario continuare a controllare l'elemento .data ("init") su ogni evento mouseover. Inoltre, è meglio usare "mouseMove", come "mouseover" non sempre ottenere innescato se il mouse è già finita l'elemento quando i calci di funzione .Live in

(function ($) { 
    $.fn.liveDraggable = function (opts) { 
     this.live("mousemove", function() { 
      $(this).draggable(opts); 
     }); 
    }; 
}(jQuery)); 

Ecco come lo si utilizza:.

$('.thing:not(.ui-draggable)').liveDraggable(); 

Il trucco è aggiungere ": not (.ui-draggable)" al tuo selettore. Poiché jQuery aggiungerà automaticamente la classe "ui-draggable" al tuo elemento quando diventa trascinabile, la funzione .live non la bersaglierà più. In altre parole, si innesca solo una volta, a differenza dell'altra soluzione che si innesca ripetutamente mentre muovi qualcosa.

Idealmente, si potrebbe semplicemente. Unbind il "mousemove", ma che non funziona con .live, purtroppo.

+2

Sì, decisamente più pulito. Cosa ne pensi di spostare l'assegno per "ui-draggable" all'interno della funzione plug-in ... qualcosa come "if (! This.hasClass ('u-draggable')) {...}"? – stldoug

+0

non è possibile utilizzare delegato. lì è possibile specificare un selettore aggiuntivo. – Luke

0

Una vecchia domanda. Ma threedubmedia ha il plugin drag and drop con supporto live (a partire dal v 1.7 noto semplicemente come "on"). http://threedubmedia.com/code/event/drop Non l'ho usato troppo per cui non posso renderlo conto delle prestazioni, ecc. Ma sembra ragionevole.

1

Un esempio:

turco:

<div id="diyalogKutusu"> 
    <div id="diyalog-baslik">..baslik..</div> 
    <div id="icerik">..icerik..</div> 
</div> 

$(document).on("mouseover", "#diyalogKutusu", function() { 
    $(this).draggable({ handle: '#diyalog-baslik' }); 
}); 

inglese:

<div id="dialogBox"> 
    <div id="dialogBox-title">..title..</div> 
    <div id="content">..content..</div> 
</div> 

$(document).on("mouseover", "#dialogBox", function() { 
    $(this).draggable({ handle: '#dialogBox-title' }); 
}); 

Nota: È possibile utilizzare al posto di on()live() o delegate. Il on() ha buone prestazioni di altri

4

Combinando le migliori risposte da @ John e @jasimmk:

Utilizzando .live:

$('li:not(.ui-draggable)').live('mouseover',function(){ 
    $(this).draggable(); // Only called once per li 
}); 

.live è deprecato, però, meglio usare .on:

$('ul').on('mouseover', 'li:not(.ui-draggable)', function(){ 
    $(this).draggable(); // Only called once per li 
}); 

Come spiegato da @john, .ui-draggable viene automaticamente aggiunto ai metodi trascinabili, quindi escludendo tale classe con il selettore, si garantisce che draggable() venga chiamato una sola volta su ciascun elemento. E l'utilizzo di .on ridurrà l'ambito del selettore, migliorando le prestazioni.

1
$("html divs to drag").appendTo("#layoutDiv").draggable(options); 

JSFiddle

0

Un'altra opzione è quella di mescolare il gestore passaggio del mouse con una classe rimovibile, in questo modo:

$('.outer-container').on('mouseover', '.my-draggable.drag-unbound', function(e) { 
    $(this).draggable().removeClass('drag-unbound'); 
}); 

E 'abbastanza semplice e risolve alcuni dei problemi che le altre risposte hanno con re -Collegando all'infinito come mouseover.

0

Una versione aggiornata che non utilizza dal vivo come è deprecato: (! JQuery (questo) .data ("init"))

function liveDraggable(selector, options) { 
    $(document).on('mouseover', selector, function() { 
     if (!$(this).data("init")) { 
      $(this).data("init", true); 
      $(this).draggable(options); 
     } 
    }); 
}