27

Quiero tener una lista que se pueda ordenar, pero también quiero que los elementos en esa lista sean desplegables a los divs que he definido como droppable. Parece que no puedo encontrar una manera de hacerlo. ¿Algunas ideas?jQuery ordenable y droppable

+0

He criado a una [solicitud de función aquí] (http://bugs.jqueryui.com/ticket/10628) –

Respuesta

21

Aquí hay una versión simplificada de la solución de Colin.

La mayor diferencia es que esta solución no almacena todo el html de los elementos ordenables, sino solo el elemento actualmente arrastrado. Luego se inserta en su posición original si el artículo se deja caer en el área que se puede colocar.

De todos modos, aquí está el código:

<!doctype html> 
<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.5/jquery-ui.js"></script> 

<script type="text/javascript"> 
$(document).ready(function() { 
    var dropped = false; 
    var draggable_sibling; 

    $("#sortable").sortable({ 
     start: function(event, ui) { 
      draggable_sibling = $(ui.item).prev(); 
     }, 
     stop: function(event, ui) { 
      if (dropped) { 
       if (draggable_sibling.length == 0) 
        $('#sortable').prepend(ui.item); 

       draggable_sibling.after(ui.item); 
       dropped = false; 
      } 
     } 
    }); 

    $(".droppable").droppable({ 
     activeClass: 'active', 
     hoverClass:'hovered', 
     drop:function(event,ui){ 
      dropped = true; 
      $(event.target).addClass('dropped'); 
     } 
    }); 
}); 

</script> 

<style type="text/css"> 
#sortable li{ 
    clear:both; 
    float:left; 
} 

.droppable { 
    clear:both; 
    height:300px; 
    width:400px; 
    background-color:#CCC; 
} 

.droppable.active { background: #CFC; } 
.droppable.hovered { background: #CCF; } 
.dropped { background: #f52; } 
</style> 

</head> 
<body> 

<ul id="sortable"> 
    <li id="one">One</li> 
    <li id="two">Two</li> 
    <li id="three">Three</li> 
    <li id="four">Four</li> 
    <li id="five">Five</li> 
    <li id="six">Six</li> 
</ul> 

<div class="droppable">Drop Here</div> 
<div class="droppable">Drop Here</div> 

</body> 
</html> 

Todavía sufre el mismo problema que la solución de Colin, si se arrastra un elemento en una nueva posición en la lista y luego se dejó caer fuera tanto el <ul> y la lanzables <div>. El artículo no se restablecerá, sino que ocupará la última posición en la lista (probado en Google Chrome). De todos modos, esto se resuelve fácilmente con un poco de detección del mouse o incluso puede ser un comportamiento deseable.

+1

Usé una variación de esto en mi proyecto. Gracias +1 –

+0

Código desde arriba http://codepen.io/tcosentino/pen/myVEEJ <- no estoy seguro de cómo terminó con "VEEJ" –

+0

¿Es realmente necesario guardar un estado y depender de su corrección? Parece que podría ser posible trabajar con los valores de desplazamiento/posición del evento del mouse de Drop. –

0

He pasado todo el día en esto, y he estado mucho más cerca, pero aún no estoy tan bien como me gustaría. Ahora tengo la funcionalidad que necesito, pero se lanza un error de Javascript.

El problema es obtener la lista ordenable para volver a su posición anterior si el elemento se descarta en la lista desplegable, en lugar de en la lista. Actualmente, estoy guardando el html onmousedown, luego reescribiendo el html en la función drop del droppable. Esto funciona, pero me da una variable jquery es un error nulo. ¿Alguien puede encontrar una mejor solución?

Código:

<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script> 
    <script type="text/javascript"> 

var templateHtml; 
$(document).ready(function(){ 

    $("#sortable").sortable(); 
    $("#sortable li").addClass("drop").bind('mousedown',function(){ 
     templateHtml = $("#sortable").html(); 
    }); 
    $("#droppable").droppable({ 
     activeClass: 'active', 
     hoverClass:'hovered', 
     accept:".drop", 
     drop:function(event,ui){ 
      $("#sortable").sortable('destroy').html(templateHtml); 
      $("#sortable").sortable(); 
      $("#sortable li").addClass("drop").bind('mousedown',function(){ 
       templateHtml = $("#sortable").html(); 
      });   
     } 
    }); 

}); 

    </script> 
    <style type="text/css"> 
    #sortable li{ 
     clear:both; 
     float:left; 
    } 

    #droppable { 
     clear:both; 
     height:300px; 
     width:400px; 
     background-color:#CCC; 
    } 
    #droppable.active { 
     background-color:#CFC; 
    } 
    #droppable.hovered { 
     background-color:#CCF; 
    } 
    </style> 

</head> 
<body> 

<ul id="sortable"> 
<li id="one">One</li> 
<li id="two">Two</li> 
<li id="three">Three</li> 
<li id="four">Four</li> 
<li id="five">Five</li> 
<li id="six">Six</li> 
</ul> 

<div id="droppable"> 
Drop Here 
</div> 

</body> 
4

Por lo que pude ver, el problema con el código anterior que he publicado es que la función de caída de la lanzables estaba siendo llamado ante el mouseup del ordenable, y desde Reescribí la lista que el ordenable se estaba enojando (por falta de mejores términos). Eso es un poco una suposición.

Mirando el código final:

<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.js"></script> 
    <script type="text/javascript"> 

var dropped = false; 
var templateHtml; 
$(document).ready(function(){ 

    setSortable(); 

    $("#droppable").droppable({ 
     activeClass: 'active', 
     hoverClass:'hovered', 
     accept:".drop", 
     drop:function(event,ui){ 
      dropped = true; 
      //alert(ui.draggable.text()); 
     } 
    }); 

}); 

function setSortable(){ 
    $("#sortable").sortable({ 
     stop:function(event,ui){ 
      if(dropped){ 
       $("#sortable").sortable('destroy').html(templateHtml); 
       dropped = false; 
       setSortable(); 
      } 
     } 
    }); 

    $("#sortable li").addClass("drop").bind('mousedown',function(){ 
     templateHtml = $("#sortable").html(); 
    }); 
} 

    </script> 
    <style type="text/css"> 
    #sortable li{ 
     clear:both; 
     float:left; 
    } 

    #droppable { 
     clear:both; 
     height:300px; 
     width:400px; 
     background-color:#CCC; 
    } 
    #droppable.active { 
     background-color:#CFC; 
    } 
    #droppable.hovered { 
     background-color:#CCF; 
    } 
    </style> 

</head> 
<body> 

<ul id="sortable"> 
<li id="one">One</li> 
<li id="two">Two</li> 
<li id="three">Three</li> 
<li id="four">Four</li> 
<li id="five">Five</li> 
<li id="six">Six</li> 
</ul> 

<div id="droppable"> 
Drop Here 
</div> 

</body> 

Toneladas de peculiaridades están implicados aquí.

me trató de salvar el html #sortable en el evento de inicio de ordenable, pero que conseguir que se llama después de todo el ui-css obtiene aplicada, y terminó la colocación de elementos de la lista de lugares locos. Entonces, necesitaba usar la función mousedown en los LI.

El setSortable está en una función porque el evento de detención reescribe el ordenable, que es "recursivo" supongo. No estoy seguro de la terminología exacta aquí, pero podemos ir con molestamente confuso.

Afortunadamente, se llama a la función de colocación del droppable antes de la función de detención sortables, por lo que pude establecer una variable global "descartada" que se usó para ver si el elemento se descartaba.

Todavía estoy sorprendido de que esto no fuera más fácil de hacer, pensé que jQuery tendría funciones para manejarlo mucho mejor. Tal vez me estoy perdiendo algo?

+0

Por favor se mi versión ligeramente simplificada. – Reimund

+0

Por favor, edite y actualice su respuesta en lugar de crear nuevas ... –

0

Pudo obtener un resultado final similar al hacer que cada uno de los DIV objetivo tuviera sus propios ordenamientos.

Luego, a través de connectWith, hice que todos los sortables pudieran conectarse y compartir arrastres.

Algo así como:

var connects = '#main_sortable, div.target'; 
$('#main_sortable').sortable({ connectWith: connect }); 
$('div').sortable({ connectWith: connect}); 
0

Si puede permitir que sus otras áreas lanzables para ser clasificable así, puede utilizar la connectWith option con un selector común:

<div id="droppable1" class="droppable-area"></div> 
<div id="droppable2" class="droppable-area"></div> 
<div id="droppable3" class="droppable-area"></div> 

su código jQuery entonces ser:

$('.droppable-area').sortable({ connectWith: '.droppable-area' }); 

Esta solución funcionó muy bien para mí y de todos modos

1

No es exactamente lo que pediste, pero necesitaba un contenedor inicial donde los artículos pudieran arrastrarse a otro contenedor clasificable, y pensé que debería compartirlo. Así fue como lo logré (jQuery 1.8.3):

$("#sortable-list").sortable(); 
$("#initial-list div").draggable({ 
    revert: true, 
    revertDuration: 0 
}); 

$("#initial-list").droppable({ 
    accept: ".item-selected", 
    drop: function(e, ui) { 
    var dropped = ui.draggable; 
    var droppedOn = $(this); 
    var itemInOtherList = $(this).children("#" + dropped.attr('id')); 
    itemInOtherList.removeClass('ui-state-disabled').draggable({ disabled: false }); 
    dropped.remove(); 
    } 
}); 
$("#sortable-list").droppable({ 
    accept: ".item-initial", 
    drop: function(e, ui) { 
    var dropped = ui.draggable; 
    var droppedOn = $(this); 
    droppedOn.append(dropped.clone() 
     .removeAttr('style') 
     .removeClass("item-initial") 
     .addClass("item-selected")); 
    dropped.animate(dropped.data().origPosition, { 
     complete: function() { 
     $(this).addClass('ui-state-disabled').draggable({ disabled: true }); 
     } 
    }); 
    } 
}); 

jsFiddle: http://jsfiddle.net/Muskar/dwz4mvxa/8/

Cuestiones relacionadas