it-swarm.com.de

jQuery Drag & Drop - Überprüfen auf einen Drop außerhalb einer Dropable

Ich entschuldige mich, wenn dies in einer anderen Frage beantwortet wurde. Ich konnte keine für mein Problem spezifische Antwort finden!

Ich versuche zu testen, ob ein jQuery-Draggable außerhalb eines legalen Dropable abgelegt wird. Dies würde normalerweise in 90% der Fälle durch Zurücksetzen des Draggable gelöst werden, aber ich möchte das nicht tun. Stattdessen möchte ich eine Sache tun, wenn das Draggable auf ein Dropable fallen gelassen wird (es funktioniert großartig!) Und etwas anderes, wenn es außerhalb aller möglichen Dropable fällt (derzeit wird es mir besser!).

In einer Nussschale:

jQuery('#droppable').droppable(
{
    accept: '#draggable',
    drop: function(event, ui)
    {
        // awesome code that works and handles successful drops...
    }
});

jQuery('#draggable').draggable(
{
    revert: false,
    stop: function()
    {
        // need some way to check to see if this draggable has been dropped
        // successfully or not on an appropriate droppable...
        // I wish I could comment out my headache here like this too...
    }
});

Ich fühle, dass mir etwas wirklich offensichtliches fehlt ... danke im Voraus für jede Hilfe!

36
Chris Kempen

Da das Drop-Event des Dropable-Objekts vor dem Stop-Event des Draggables ausgelöst wird, können Sie meiner Meinung nach ein Flag für das Element setzen, das im Drop-Event gezogen wird.

jQuery('#droppable').droppable(
{
    accept: '#draggable',
    drop: function(event, ui)
    {
        ui.helper.data('dropped', true);
        // awesome code that works and handles successful drops...
    }
});

jQuery('#draggable').draggable(
{
    revert: false,
    start: function(event, ui) {
        ui.helper.data('dropped', false);
    },
    stop: function(event, ui)
    {
        alert('stop: dropped=' + ui.helper.data('dropped'));
        // Check value of ui.helper.data('dropped') and handle accordingly...
    }
});
53
Luke Girvin

Ich sehe, dass Sie bereits eine Antwort erhalten haben. Trotzdem hatte ich heute dasselbe Problem und habe es so gelöst:

var outside = 0;

// this one control if the draggable is outside the droppable area
$('#droppable').droppable({
    accept      : '.draggable',
    out         : function(){
        outside = 1;
    },
    over        : function(){
        outside = 0;
    }
});

// this one control if the draggable is dropped
$('body').droppable({
    accept      : '.draggable',
    drop        : function(event, ui){
        if(outside == 1){
            alert('Dropped outside!');
        }else{
            alert('Dropped inside!');
        }
    }
});

Ich brauchte das, weil ich die Optionen meiner Draggables nicht ändern konnte, also musste ich nur mit Droppables arbeiten (ich brauchte es im awesome FullCalendar plugin) .. Ich denke, es könnte Probleme mit dem "gierige" Option von Droppables, sollte aber in den meisten Fällen funktionieren.

PS: Entschuldigung für mein schlechtes Englisch.

EDIT: Wie vorgeschlagen, habe ich die Version mit jQuery.data erstellt. es kann hier gefunden werden: jsfiddle.net/Polmonite/WZma9/

Die Dokumentation zu jQuery.data besagt jedoch:

Beachten Sie, dass diese Methode derzeit keine plattformübergreifende Unterstützung für das Festlegen von Daten in XML-Dokumenten bietet, da Internet Explorer das Anfügen von Daten über expando -Eigenschaften nicht zulässt.

(was bedeutet, dass es auf IE vor 8 nicht funktioniert)

EDIT 2: Wie von @Darin Peterson angemerkt, funktioniert der vorherige Code nicht mit mehr als einem Drop-Bereich. Dies sollte das Problem beheben: http://jsfiddle.net/Polmonite/XJCmM/

EDIT 3: Beispiel aus EDIT 2 hat einen Fehler. Wenn ich "Drag me!" Nach unten droppable, dann "Drag me too" zur oberen Dropbox und dann "Drag me too" nach außen, es wird "Dropped inside!" Verwenden Sie es also nicht.

EDIT 4: Wie von @Aleksey Gor festgestellt, war das Beispiel in Edit 2 falsch. Eigentlich war es eher ein Beispiel, um zu erklären, wie man alle Draggables/Droppables durchläuft, aber ich habe eigentlich vergessen, die Alarmmeldungen zu entfernen, daher war es ziemlich verwirrend. Hier die aktualisierte Geige.

9
Polmonite

Versuchen Sie, das Ereignis "out" eines droppable - Elements zu verwenden.

Dies ist die Dokumentation

"Dieses Ereignis wird ausgelöst, wenn ein akzeptiertes Draggable-Objekt (innerhalb der Toleranz von) dieses Dropable-Objekt herausgezogen wird." Wenn ich recht habe, ist dies das, was Sie brauchen.

Es ist auch möglich, eine Elementüberlagerung über die gesamte Seite zu erstellen. Wenn das Element dort abgelegt wird, feuern Sie Ihr Ereignis ab. Nicht das Beste, aber ich denke, der einzige Weg, es zu tun. Weil Sie einen anderen "abwerfbaren" Gegenstand benötigen, um diese Ereignisse auszulösen.

4
ggzone

Der Vorteil des folgenden Beispiels ist, dass Sie den droppbaren Code nicht ändern müssen oder wissen müssen:

Die Draggable Revert-Eigenschaft kann eine Funktion (Wert) {} haben. Ein Wert wird als Argument übergeben, der angibt, ob der Helfer auf ein Element (das Drop-Element) abgelegt wurde, oder 'false', wenn er nicht auf ein Element (Drop-Drop oder nicht akzeptiert) fällt. 

Hinweis: Sie müssen den korrekten Bool-Wert von diesem .__ zurückgeben. revert-function, um dem Helfer mitzuteilen, dass er zurückkehren soll oder nicht (wahr falsch). "True" bedeutet "Ja". Bringen Sie den Helfer in die ursprüngliche Position Position, indem Sie ihn in einer Zeitlupe zurückschieben (out-of-the-box). Falsch bedeutet nein, nur entferne den Helfer abrupt. Festlegen der Eigenschaft "revert" auf "ungültig", ist eine Abkürzung für das Sprichwort 

  • "Ja, wenn draußen nach draußen fallen, dann Helfer umkehren"
  • 'nein, wenn auf ein abwerfbares Element fallen gelassen und akzeptiert, dann töten Sie den Helfer sofort'.

Meine Vermutung ist, dass Sie den aktuellen UI-Helper während des Startereignisses zu einem Container mit Dateneigenschaften ziehen können. Nehmen Sie es dann in der Rückgabefunktion von der Dateneigenschaft auf. Fügen Sie dann dem Helper eine Eigenschaft hinzu, die angibt, ob er fallen gelassen wurde oder nicht. Überprüfen Sie anschließend im Stoppereignis diesen Wert der Dateneigenschaft, und tun Sie, was Sie beabsichtigen.

Reihenfolge der Ereignisse/Funktionen für Draggable: Start-revert-stop

Dies könnte ein Beispiel sein:

jQuery('#draggable').draggable(
{
    start: function(event, ui) {
        $(this).data('uihelper', ui.helper);
    },
    revert: function(value){
        var uiHelper = (this).data('uihelper');
        uiHelper.data('dropped', value !== false);
        if(value === false){
             return true;
        }
        return false;
    },
    stop: function(event, ui)
    {
        if(ui.helper.data('dropped') === true){
            // handle accordingly...
        }
    }
});

Sie können sogar in der Rückgabefunktion true zurückgeben und den Helper stattdessen während des Stoppereignisses entfernen. Dies hängt von dem Datenwert ('drop') mit ui.helper.remove () ab. Oder Sie könnten es sogar mit CSS3 explodieren, wenn Sie noch einen schlechten Tag haben;)

1
Bogmag

Alte Fragen und alte Antworten bedeuten, dass dies eine neue Lösung sein kann. Sie wollten (vielleicht) auch, wie die Frage besagt, wissen, WENN ein Draggable außerhalb eines Dropgables abgelegt wurde. Für mich ist es in mindestens 95% der Fälle egal, ob die Dinge wieder so sind, wie sie waren, ohne dass Änderungen vorgenommen wurden, WANN das passiert.

Das Setzen von revert auf die Zeichenfolge invalid führt zum gewünschten Verhalten, ohne dass zusätzlicher Code oder irre Dinge zu tun sind.

$( '#draggable' ).draggable({
    revert: "invalid",
    stop: function( event, ui )
    {
       // whatever
    }
});

Auch hier wird Ihnen nicht mitgeteilt, "ob es außerhalb eines Ablegegeräts abgelegt wurde", aber in diesem Fall wird der ursprüngliche Zustand wiederhergestellt.

0
Chris Ostmo

Ich füge die Lösung hinzu, die ich angenommen habe, da Sie dies leicht anhand der CSS-Klassen des Objekts verstehen können, das Sie verschieben:

jQuery('#draggable').draggable({
  stop: function(event, ui) {
    if (ui.helper.hasClass('ui-draggable-dragging')) {
      console.log('dropped out');
    } else {
      console.log('dropped successfully');
    }
  }
});
0
coorasse