example - jquery draggable sortable
Revertir un objeto arrastrable de jQuery a su contenedor original en el evento out de droppable (5)
PROBADO con jquery 1.11.3 y jquery-ui 1.11.4
$(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();
});
Tengo un elemento arrastrable que, si no se deja caer en un droppable, se revertirá. Esto funciona bien hasta que un usuario suelta un elemento en el droppable. Si deciden que han cometido un error cada vez que retiran el dispositivo de arrastre, vuelve al área de despliegue. Preferiría que fuera y desactivar el arrastrable regrese a su contenedor original.
Mi código está debajo pero he proporcionado una muestra en 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 };
});
}
});
});
En caso de que alguien esté interesado, esta es mi solución al problema. Funciona de forma completamente independiente de los objetos arrastrables, mediante el uso de eventos en el objeto desplegable en su lugar. Funciona bastante 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''});
}
Está relacionado con el origen revertido: para establecer el origen cuando se arrastra el objeto: simplemente use $(this).data("draggable").originalPosition = {top:0, left:0};
Por ejemplo: uso así
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);
}
No estoy seguro de si esto funcionará para su uso real, pero funciona en su caso de prueba, actualizado en http://jsfiddle.net/sTD8y/27/ .
Acabo de hacerlo de manera que la reversión incorporada solo se use si el elemento no se ha caído antes. Si se ha eliminado, la reversión se realiza de forma manual. Podrías ajustar esto para animar a una compensación calculada verificando las propiedades de CSS reales, pero te dejaré jugar con eso porque mucho depende del CSS del arrastrable y de la estructura DOM que lo rodea.
$(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);
}
});
});
Si desea revertir el elemento a la posición de origen si no se deja caer dentro de un elemento #droppable
, simplemente guarde el elemento padre original del elemento que se puede arrastrar al inicio del script (en lugar de la posición), y si verifica que no es soltado en #droppable
, luego simplemente restaure el padre de #draggable
a este elemento original.
Entonces, reemplace esto:
}).each(function() {
var top = $(this).position().top;
var left = $(this).position().left;
$(this).data(''orgTop'', top);
$(this).data(''orgLeft'', left);
});
con este:
}).each(function() {
$(this).data(''originalParent'', $(this).parent())
});
Aquí, tendrá el elemento padre original del arrastrable. Ahora, debes restaurar su padre en un momento preciso.
drop
se invoca cada vez que se arrastra el elemento desde el elemento desplegable, no desde el stop. Por lo tanto, está agregando una gran cantidad de devoluciones de llamadas de eventos. Esto es incorrecto, porque nunca se limpia el evento mouseup
. Un buen lugar donde puede conectar una devolución de llamada y verificar si el elemento se #droppable
dentro o fuera del elemento #droppable
, se revert
, y lo está haciendo en este momento, por lo tanto, simplemente elimine la drop
llamada perdida.
Cuando el elemento se descarta y necesita saber si debe revertirse o no, usted está seguro de que no tendrá ninguna otra interacción del usuario hasta que se inicie el nuevo arrastre. Entonces, usando la misma condición que está utilizando para saber si debería revertirse o saber, reemplacemos esta alert
con un fragmento de código que: restaure el elemento padre al div original y restablezca la posición originalPosition
de las draggable
internas que se pueden draggable
. La propiedad originalPosition
configura en el momento de _mouseStart
, por lo tanto, si cambia el propietario del elemento, debe restablecerlo para que la animación de reversión vaya al lugar adecuado. Entonces, establezcamos esto en {top: 0, left: 0}
, haciendo que la animación vaya al punto de origen del elemento:
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;
}
¡Y eso es! Puede verificar esto trabajando aquí: http://jsfiddle.net/eUs3e/1/
Tenga en cuenta que, si en cualquier actualización de la interfaz de usuario de jQuery, el comportamiento de revert
o la revert
originalPosition
cambia, deberá actualizar su código para que funcione. Manten eso en mente.
Si necesita una solución que no haga llamadas a las partes internas de ui.draggable, puede hacer que su body
un elemento que se pueda eliminar con la opción greedy
definida como false
. Tendrás que asegurarte de que los elementos de tu body
ocupen toda la pantalla.
¡Buena suerte!