web-dev-qa-db-fra.com

jQuery drag and drop - recherche d'une goutte en dehors d'une liste de dépôt

Mes excuses si cela a été répondu dans une autre question, je ne pouvais pas trouver une réponse spécifique à mon problème!

J'essaie de tester si un jQuery draggable est largué en dehors d'un droppable légal. Cela serait normalement résolu 90% du temps en inversant le glissable, mais je ne veux pas le faire. Au lieu de cela, je veux faire une chose si le draggable est déposé sur une bave (très bien!), Et quelque chose d’autre si elle est laissée en dehors de toutes les droppables possibles (prenant actuellement le dessus sur moi!).

En un mot:

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

J'ai l'impression qu'il me manque quelque chose de vraiment évident ... merci d'avance pour toute aide!

36
Chris Kempen

Étant donné que l'événement drop de droppable est déclenché avant l'événement stop du draggable, je pense que vous pouvez définir un indicateur sur l'élément en cours de déplacement dans l'événement drop, comme suit:

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

Je vois que tu as déjà eu une réponse; de toute façon, j'ai eu le même problème aujourd'hui et je l'ai résolu de cette façon:

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

J'avais besoin de ça parce que je ne pouvais pas changer les options de mes objets draggables, donc je ne devais travailler qu'avec droppables (j'en avais besoin dans le génial FullCalendar plugin) option "gourmande" de droppables, mais cela devrait fonctionner dans la plupart des cas.

PS: désolé pour mon mauvais anglais.

EDIT: Comme suggéré, j'ai créé la version en utilisant jQuery.data; on peut le trouver ici: jsfiddle.net/Polmonite/WZma9/

Quoi qu'il en soit, la documentation jQuery.data dit:

Notez que cette méthode ne fournit actuellement pas de support multiplateforme pour la définition de données sur des documents XML, car Internet Explorer n'autorise pas la liaison de données à l'aide de propriétés expando.

(ce qui signifie que cela ne fonctionne pas sur IE avant 8)

EDIT 2: Comme l'a noté @Darin Peterson, le code précédent ne fonctionne pas avec plus d'une zone de dépôt; cela devrait résoudre ce problème: http://jsfiddle.net/Polmonite/XJCmM/

EDIT 3: Exemple de EDIT 2 a un bogue. Si je fais glisser "Drag me!" en bas de la liste, puis déposez "Glissez-moi aussi" en haut, puis déposez-la "Glissez-moi aussi" à l'extérieur, cela signale "Goutte à l'intérieur!". Alors, ne l'utilisez pas.

EDIT 4: Comme l'a noté @Aleksey Gor, l'exemple de Edit 2 était faux; en fait, c’était plus un exemple pour expliquer comment faire une boucle entre tous les objets draggables/droppables, mais j’ai en fait oublié de supprimer les messages d’alerte, c’était donc assez déroutant. Ici le violon mis à jour.

9
Polmonite

Essayez d'utiliser l'événement "out" d'un élément droppable.

Ceci est la documentation

"Cet événement est déclenché lorsqu'un objet accepté que l'on accepte est déplacé (dans les limites de la tolérance de) par cette valeur.".

Ce qui est également possible est de créer une superposition d’élément sur toute la page. Si l'élément y est déposé, vous déclenchez votre événement. Pas le meilleur, mais je pense que la seule façon de le faire. Parce que vous avez besoin d'un autre objet "largable" pour déclencher ces événements.

4
ggzone

L'avantage de l'exemple suivant est que vous n'avez pas besoin de changer ou de connaître le code de la droppable:

La propriété draggable revert peut avoir une fonction (valeur) {}. Une valeur est transmise en tant qu'argument, indiquant si helper a été déposé sur un élément (l'élément drop), ou 'false' si non déposé sur un élément (déposer en dehors ou non accepté). 

Remarque: vous devez renvoyer la valeur booléenne correcte à partir de cela revert-function, afin de dire à l’assistant de revenir en arrière ou non (vrai faux). Vrai signifie oui, ramener l’assistant à son origine position, en le déplaçant vers l'arrière au ralenti (par défaut). Faux signifie non, juste retirer l'assistant abdruptly. Paramétrer la propriété revert sur 'invalid', est un raccourci de dire 

  • 'oui, si laissé tomber dehors, puis revenir aide'
  • 'Non, si on le laisse tomber sur un élément de la bave et qu'il est accepté, tuez l'assistant tout de suite'.

Mon hypothèse est que vous pouvez ajouter l'aide actuelle de l'interface utilisateur au conteneur déplaçable avec la propriété data au cours de l'événement de démarrage. Ensuite, sélectionnez-le dans la fonction de restauration de la propriété data. Ajoutez ensuite une propriété à l’assistant, indiquant si elle a été supprimée ou non. Ensuite, dans l'événement stop, vérifiez cette valeur de propriété de données et faites ce que vous souhaitez.

Ordre des appels d’événements/fonctions pour les éléments glissables: Start-revert-stop

Cela pourrait être un exemple:

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

Vous pouvez même renvoyer true dans la fonction de retour et simplement supprimer le helper lors de l'événement stop, en fonction de la valeur data ('drop') avec ui.helper.remove (). Ou vous pourriez même l'exploser avec CSS3 si vous avez encore une mauvaise journée;)

1
Bogmag

J'ajoute la solution que j'ai adoptée car vous pouvez le comprendre très facilement à partir des classes CSS de l'objet que vous déplacez

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