2009-11-26 8 views
41

Ich habe eine Anwendung mit einer langen Liste, die sich häufig ändert, und ich brauche die Elemente dieser Liste ziehbar sein.jQuery Drag & Drop mit Live-Events

Ich habe das juguerable UI-Drag-in-Plugin verwendet, aber es ist langsam, um mehr als 400 Listenelemente hinzuzufügen, und muss jedes Mal neu hinzugefügt werden, wenn neue Listenelemente hinzugefügt werden.

Kennt jemand ein Plugin, das dem jQuery UI-Drag-in-Plugin ähnlich ist, das die .live()-Ereignisse von jQuery 1.3 verwendet? Dies würde beide Probleme lösen.

+0

Was bedeutet 'if {jQuery (this) .data ("init", wahr);} tun? –

Antwort

44

Wojteks Lösung funktionierte perfekt für mich. Ich zog es ein bisschen etwas zu ändern, um es jQuery ...

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

Jetzt zu machen zu verlängern, anstatt sie zu nennen mag:

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

... nur verwenden:

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

Das hat meine js zusammen gebrochen. Müssen Sie das irgendwo einfügen, um die JQuery-Funktionalität zu erweitern? – Andrew

+1

Sie müssen es nach dem Laden von jQuery deklarieren und bevor Sie es in Ihrem Code verwenden. Welchen Fehler bekommst du? – stldoug

+0

Super danke! – Chris

10

Sie können Wrapper-Funktion wie diese machen:

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

(Ich benutze Prototyp mit jQuery - das ist, warum ich jQuery platziert() anstelle von $())

Und jetzt statt $ (Selektor) .raggable ({opts}) benutze liveDraggable (selector, {opts})

+0

Das funktionierte perfekt für mich, danke. – Wil

21

Dies ist ein Beispiel für einen Code, der perfekt für mich funktioniert.

+0

verwenden, das wie ein Zauber für mich funktioniert, danke – Raz

+0

+1 es ist die einfachste Lösung. – enloz

+3

es ist eine einfache Lösung, aber ziehbar ist auf alle DOM-Elemente mit Gadgets-Spalte Klasse * jedes Mal * Sie einen der Mauszeiger über ... –

7

Der Code von Stdoug hat für mich funktioniert, aber es ist nicht nötig, die .data ("init") des Elements bei jedem mouseover-Ereignis zu überprüfen. Außerdem ist es besser „mousemove-“, als „Mouseover“ zu verwenden, nicht immer ausgelöst werden, wenn Sie mit der Maus bereits über das Element ist, wenn die .live Funktion Tritte in

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

Hier ist, wie Sie es verwenden.

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

Der Trick besteht darin, "" nicht (.ui-ziehbare) "zu Ihrem Selektor hinzuzufügen. Da jQuery automatisch die Klasse "ui-draggable" zu Ihrem Element hinzufügt, wenn es ziehbar wird, wird es von der .live-Funktion nicht mehr als Ziel verwendet. Mit anderen Worten, es löst nur einmal aus, im Gegensatz zu der anderen Lösung, die immer wieder auslöst, wenn Sie etwas herum bewegen.

Im Idealfall könnten Sie einfach den "Mauszeiger" losbinden, aber das funktioniert leider nicht mit .Live.

+2

Ja, auf jeden Fall sauberer. Was denkst du darüber, den Check für "ui-draggable" innerhalb der Plug-in-Funktion zu verschieben? Etwas wie "if (! This.hasClass ('ui-draggable')) {...}"? – stldoug

+0

können Sie stattdessen delegate nicht verwenden. Dort können Sie einen zusätzlichen Selektor angeben. – Luke

0

Eine alte Frage. Aber threedubmedia hat Drag & Drop Plugin mit Live (ab Version 1.7 bekannt als einfach "on"). http://threedubmedia.com/code/event/drop Haben Sie es nicht zu viel verwendet, so kann ich es Leistung usw. nicht erklären, aber sieht vernünftig aus.

1

Ein Beispiel:

Türkisch:

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

Englisch:

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

Hinweis: Sie on() statt live() oder delegate verwenden können. Die on() hat eine gute Leistung als andere

4

die besten Antworten von @John und @jasimmk Kombination:

Mit .live:

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

.live obwohl veraltet, besser .on zu verwenden:

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

Wie @John erklärt, wird .ui-draggable automatisch zu ziehbaren Methoden hinzugefügt. Wenn Sie also diese Klasse mit dem Selektor ausschließen, stellen Sie sicher, dass ziehbare() nur einmal für jedes Element aufgerufen wird. Und die Verwendung von .on reduziert den Umfang des Selektors und verbessert die Leistung.

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

JSFiddle

0

Eine weitere Option ist die Mouseover-Handler mit einer abnehmbaren Klasse zu mischen, etwa so:

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

Es ziemlich einfach ist und löst einige der Probleme, die anderen Antworten mit re haben -Bindung immer und immer wieder, wenn Sie den Mauszeiger darüber bewegen.

0

Eine aktualisierte Version, die nicht Live nicht verwenden, da es veraltet ist: (! JQuery (this) .data ("init"))

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