64 votes

Revenir jQuery objet déplaçable vers son conteneur d'origine sur le cas de drop

J'ai un élément déplaçable qui si n'est pas tombé dans un droppable reviendra. Cela fonctionne bien jusqu'à ce qu'un utilisateur supprime un élément dans la droppable. S'ils décident qu'ils ont fait une erreur quand ils tirent la déplaçable, il revient à la droppable. Je préférerais que sur et désactiver le déplaçable en va vers son conteneur d'origine.

Mon code est ci-dessous, mais j'ai fourni un échantillon sur jsFiddle.

HTML

<div id="origin">
    <div id="draggable" class="ui-widget-content">
        <p>I revert when I'm not dropped</p>
    </div>
</div>
<div id="droppable" class="ui-widget-header">
    <p>Drop me here</p>
</div>

JavaScript

$(function() {
    $("#draggable").draggable({ 
        revert:  function(dropped) {
           var dropped = dropped && dropped[0].id == "droppable";
           if(!dropped) alert("I'm reverting!");
           return !dropped;
        } 
    }).each(function() {
        var top = $(this).position().top;
        var left = $(this).position().left;
        $(this).data('orgTop', top);
        $(this).data('orgLeft', left);
    });

    $("#droppable").droppable({
        activeClass: 'ui-state-hover',
        hoverClass: 'ui-state-active',
        drop: function(event, ui) {
            $(this).addClass('ui-state-highlight').find('p').html('Dropped!');
        },
        out: function(event, ui) {
                // doesn't work but something like this
                ui.draggable.mouseup(function () {
                var top = ui.draggable.data('orgTop');
                var left = ui.draggable.data('orgLeft');
                ui.position = { top: top, left: left };
            });
        }
    });
});

137voto

aSeptik Points 19103

Mis à JOUR pour fonctionner avec jQuery 1.9 version

$(function() {
    $("#draggable").draggable({
        revert : function(event, ui) {
            // on older version of jQuery use "draggable"
            // $(this).data("draggable")
            // on 2.x versions of jQuery use "ui-draggable"
            // $(this).data("ui-draggable")
            $(this).data("uiDraggable").originalPosition = {
                top : 0,
                left : 0
            };
            // return boolean
            return !event;
            // that evaluate like this:
            // return event !== false ? false : true;
        }
    });
    $("#droppable").droppable();
});

9voto

BBonifield Points 3106

Je ne suis pas sûr si cela fonctionne pour votre usage réel, mais il fonctionne dans votre cas de test - mise à jour au http://jsfiddle.net/sTD8y/27/ .

J'ai juste fait en sorte que le construit en revenir n'est utilisé que si l'élément n'a pas été abandonné à l'avant. Si elle a été abandonnée, le revert est fait manuellement. Vous pouvez ajuster ce pour animer certains calculé compensée par la vérification de l'effectif des propriétés CSS, mais je vais vous laisser jouer avec ça parce que beaucoup de cela dépend de la CSS de la déplaçable et ses environs DOM structure.

$(function() {
    $("#draggable").draggable({
        revert:  function(dropped) {
             var $draggable = $(this),
                 hasBeenDroppedBefore = $draggable.data('hasBeenDropped'),
                 wasJustDropped = dropped && dropped[0].id == "droppable";
             if(wasJustDropped) {
                 // don't revert, it's in the droppable
                 return false;
             } else {
                 if (hasBeenDroppedBefore) {
                     // don't rely on the built in revert, do it yourself
                     $draggable.animate({ top: 0, left: 0 }, 'slow');
                     return false;
                 } else {
                     // just let the built in revert work, although really, you could animate to 0,0 here as well
                     return true;
                 }
             }
        }
    });

    $("#droppable").droppable({
        activeClass: 'ui-state-hover',
        hoverClass: 'ui-state-active',
        drop: function(event, ui) {
            $(this).addClass('ui-state-highlight').find('p').html('Dropped!');
            $(ui.draggable).data('hasBeenDropped', true);
        }
    });
});

4voto

bnrup Points 56

Dans le cas où ça intéresse quelqu'un, voici ma solution au problème. Il fonctionne de manière totalement indépendante de la Glisser des objets, en utilisant des événements sur le Drop de l'objet à la place. Il fonctionne très bien:

$(function() {
    $(".draggable").draggable({
        opacity: .4,
        create: function(){$(this).data('position',$(this).position())},
        cursor:'move',
        start:function(){$(this).stop(true,true)}
    });

    $('.active').droppable({
        over: function(event, ui) {
            $(ui.helper).unbind("mouseup");
        },
        drop:function(event, ui){
            snapToMiddle(ui.draggable,$(this));
        },
        out:function(event, ui){
            $(ui.helper).mouseup(function() {
                snapToStart(ui.draggable,$(this)); 
            });
        }
    });
}); 

function snapToMiddle(dragger, target){
    var topMove = target.position().top - dragger.data('position').top + (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
    var leftMove= target.position().left - dragger.data('position').left + (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
    dragger.animate({top:topMove,left:leftMove},{duration:600,easing:'easeOutBack'});
}
function snapToStart(dragger, target){
    dragger.animate({top:0,left:0},{duration:600,easing:'easeOutBack'});
}

4voto

Gonzalo Larralde Points 2180

Si vous souhaitez revenir à l'élément à la position de la source, si elle n'est pas tombée à l'intérieur d'un #droppable élément, il suffit de sauvegarder l'original de l'élément parent de l'déplaçable au début du script (au lieu de la position), et si vous vérifiez qu'il n'est pas tombé dans l' #droppable, puis il suffit de restaurer le parent d' #draggable de cet élément d'origine.

Donc, remplacer ce:

}).each(function() {
    var top = $(this).position().top;
    var left = $(this).position().left;
    $(this).data('orgTop', top);
    $(this).data('orgLeft', left);
});

avec ceci:

}).each(function() {
    $(this).data('originalParent', $(this).parent())
});

Ici, vous aurez l'original de l'élément parent de l'déplaçable. Maintenant, vous devez rétablir sa mère dans un moment précis.

drop est appelée chaque fois que l'élément est traîné hors de la droppable, pas à l'arrêt. Donc, vous êtes en ajoutant beaucoup de rappels d'événements. C'est faux, car vous ne nettoyez jamais l' mouseup événement. Un bon endroit où vous pouvez brancher un rappel et de vérifier si l'élément a été abandonné à l'intérieur ou à l'extérieur de l' #droppable élément, est - revert, et vous êtes en train de faire maintenant, donc, il suffit de supprimer l' drop de rappel.

Lorsque l'élément est supprimé, et a besoin de savoir si elle doit être annulées ou pas, vous savez pour sûr que vous n'aurez pas toute interaction de l'utilisateur jusqu'à ce que le nouveau début de glissement. Donc, en utilisant le même état que vous utilisez pour savoir si elle devrait revenir ou de savoir, nous allons remplacer cette alert avec un fragment de code qui: restaure le parent de l'élément à l'origine de la div, et réinitialise l' originalPosition de la draggable internes. L' originalPosition si elle est sertie au moment de l' _mouseStart, de sorte que, si vous modifiez le propriétaire de l'élément, vous devez le réinitialiser, afin de rendre l'animation de revenir aller à l'endroit approprié. Donc, nous allons mettre cela à l' {top: 0, left: 0}, faisant de l'animation d'aller vers le point d'origine de l'élément:

revert: function(dropped) {
    var dropped = dropped && dropped[0].id == "droppable";
    if(!dropped) {
        $(this).data("draggable").originalPosition = {top:0, left:0}
        $(this).appendTo($(this).data('originalParent'))
    }
    return !dropped;
}

Et c'est tout! Vous pouvez le vérifier sur ce travail ici: http://jsfiddle.net/eUs3e/1/

Prendre en considération le fait que, en cas de jQuery INTERFACE utilisateur mise à jour, le comportement de l' revert ou originalPosition modifications, vous devrez mettre à jour votre code afin de le faire fonctionner. Gardez à l'esprit que.

Si vous avez besoin d'une solution qui permet de ne pas utiliser les appels à l'intérieur de l'interface utilisateur.déplaçable, vous pouvez faire votre body un drop élément avec greedy option définie comme false. Vous aurez à vous assurer que votre body éléments à prendre la totalité de l'écran.

Bonne chance!

1voto

Xjet Points 134

C'est lié au sujet de revenir origine : pour définir le point d'origine lorsque l'objet est de glisser : il suffit d'utiliser $(this).data("draggable").originalPosition = {top:0, left:0};

Par exemple : j'utilise comme ceci

               drag: function() {
                    var t = $(this);
                    left = parseInt(t.css("left")) * -1;
                    if(left > 0 ){
                        left = 0;
                        t.draggable( "option", "revert", true );
                        $(this).data("draggable").originalPosition = {top:0, left:0};
                    } 
                    else t.draggable( "option", "revert", false );

                    $(".slider-work").css("left",  left);
                }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X