27

Je veux avoir une liste qui soit triable, mais je veux aussi que les éléments de cette liste soient droppables pour les divs que j'ai définis comme droppable. Je n'arrive pas à trouver un moyen de le faire. Des idées?jQuery Sortable and Droppable

+0

J'ai soulevé une [demande de fonctionnalité ici] (http://bugs.jqueryui.com/ticket/10628 –

Répondre

21

Voici une version simplifiée de la solution de Colin.

La plus grande différence est que cette solution ne stocke pas l'intégralité du code HTML des éléments triables, mais uniquement l'élément actuellement déplacé. Il est ensuite inséré dans sa position d'origine si l'objet est déposé sur la zone de dépôt.

Quoi qu'il en soit, voici le code:

<!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> 

Il souffre toujours le même problème que la solution de Colin si un élément est entraîné dans une nouvelle position dans la liste, puis a chuté à l'extérieur à la fois la <ul> et la <div> largable. L'élément ne sera alors pas réinitialisé mais prendra la dernière position dans la liste (testé dans Google Chrome). Quoi qu'il en soit, ceci est facilement résolu avec un peu de détection de la souris ou peut-être même un comportement souhaitable.

+1

Utilisé une variation de ceci sur mon projet. Merci +1 –

+0

Code d'en haut http://codepen.io/tcosentino/pen/myVEEJ <- je ne sais pas comment il s'est retrouvé avec "VEEJ" –

+0

Est-il vraiment besoin de sauvegarder un état et de dépendre de son exactitude? Il semble qu'il puisse être possible de travailler avec les valeurs de position/de décalage d'événement de la souris. –

0

J'ai passé toute la journée là-dessus, et je me suis beaucoup rapproché, mais je ne réussis toujours pas aussi bien que je le voudrais. J'ai maintenant la fonctionnalité dont j'ai besoin, mais une erreur Javascript est levée.

Le problème est que la liste triable retourne à sa position précédente si l'élément est déposé dans la liste déroulante plutôt que dans la liste. Actuellement, je sauve le html onmousedown, puis réécrit le html dans la fonction drop de la droppable. Cela fonctionne, mais en me donnant une variable jquery est une erreur nulle. Quelqu'un peut-il trouver une meilleure solution?

code:

<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

Pour autant que je sache, le problème avec le code précédent j'ai posté est que la fonction de chute du largable allait s'appeler avant la mouseup du sortable, et depuis que je réécris la liste le sortable devenait fâché (par manque de meilleures conditions). C'est un peu une supposition.

En regardant le code 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> 

Des tonnes de bizarreries sont impliqués ici. J'ai essayé d'enregistrer le html #sortable sur l'événement start de sortable, mais ça s'appelle après que tous les ui-css soient appliqués, et a fini par placer des éléments de liste dans des endroits fous. Donc, j'ai besoin d'utiliser la fonction mousedown sur les LI. Le setSortable est dans une fonction car l'événement stop réécrit le triable, ce qui est "récursif", je suppose. Pas sûr de la terminologie exacte ici, mais nous pouvons aller avec déroutant déroutant. Heureusement, la fonction drop de la droppable est appelée avant la fonction d'arrêt des sortables, donc j'ai été capable de définir une variable globale "drop" qui a été utilisée pour voir si l'élément a été abandonné. Je suis toujours surpris que ce n'était pas plus facile à faire, je pensais que jQuery aurait des fonctions pour le gérer beaucoup mieux. Peut-être qu'il me manque quelque chose?

+0

Se il vous plaît me voir ma version légèrement simplifiée. – Reimund

+0

S'il vous plaît [modifier] et mettre à jour votre réponse plutôt que d'en créer de nouvelles ... –

0

Était en mesure d'obtenir un résultat final similaire en rendant chacun des DIVs cibles leurs propres sortables.J'ai ensuite, via connectWith, fait tous les sortables capables de se connecter et de partager des draggables.

Quelque chose comme:

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

Si vous pouvez permettre à vos autres largables à triables aussi bien, vous pouvez utiliser le connectWith option avec un sélecteur commun:

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

votre code jQuery serait alors être:

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

Cette solution a fonctionné magnifiquement pour moi un oui.

1

Pas exactement ce que vous avez demandé, mais j'avais besoin d'un conteneur initial où les articles pourraient être traînés vers un autre conteneur triable - et j'ai pensé que je devais le partager. Ce fut ainsi que je parvins (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/