Search code examples
jquery-uijquery-ui-sortablejquery-ui-draggablejquery-ui-droppable

Jquery Sortable Draggable or Droppable Multiple Lists to One List and Revert


I am making a sortable grocery list, but I cannot figure out the best way to remove an item from the sorted list and have it go back to the original category.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Draggable + Sortable</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <style>
  ul { list-style-type: none; margin: 0; padding: 0; margin-bottom: 10px; }
  li { margin: 5px; padding: 5px; width: 150px; }
  #sortable {border: 1px solid #000; min-height:100px;}
  </style>
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <script>
  $( function() {
    $( "#sortable" ).sortable({
      connectWith: '.connectedList'
    });
    $( ".draggable" ).draggable({
      connectToSortable: "#sortable",
      revert: "invalid"
    });
    $( "ul, li" ).disableSelection();
  } );
  </script>
</head>
<body>
<h3>Fruit</h3> 
<ul id="FruitCollection" class="fruits connectedList">
  <li class="draggable">Apples</li>
  <li class="draggable">Oranges</li>
</ul>
<h3>Meat</h3> 
<ul id="MeatCollection" class="meats connectedList">
  <li class="draggable">Beef</li>
  <li class="draggable">Chicken</li>
  <li class="draggable">Pork</li>
</ul>
<h3>Dairy</h3> 
<ul id="DairyCollection" class="dairy connectedList">
  <li class="draggable">Cheese</li>
  <li class="draggable">Milk</li>
  <li class="draggable">Sour Cream</li>
  <li class="draggable">Yogurt</li>
</ul>
 
 <h2>Grocery List</h2>
<ul id="sortable">
 
</ul>
 
 
</body>
</html>

I am not sure how connectWith really works. It seems like this is an already solved problem using a combination of draggable, droppable, or sortable. Each category's items should only return back to it if removed from the sortable.

For example, drag cheese into the grocery list, but then remove it by dragging it out of the bordered, sortable. Cheese should go back to the Dairy list.


Solution

  • It might be easier to add a Delete type of icon that the User can click. Example:

    $(function() {
      function returnToList(item) {
        var t = $("." + $(item).data("list"));
        $(item)
          .detach()
          .appendTo(t);
        $(".ui-icon", item).remove();
      }
    
      function addDel(item) {
        $("<span>", {
          class: "ui-icon ui-icon-close"
        }).appendTo(item);
      }
    
      $("#sortable").sortable({
        stop: function(e, ui) {
          if ($(".ui-icon", ui.item).length < 1) {
            addDel(ui.item);
          }
        }
      });
      $(".items li").draggable({
        connectToSortable: "#sortable",
        revert: "invalid"
      });
      $("ul, li").disableSelection();
    
      $(".list").on("click", "li .ui-icon-close", function() {
        returnToList($(this).parent());
      });
    });
    ul {
      list-style-type: none;
      margin: 0;
      padding: 0;
      margin-bottom: 10px;
    }
    
    li {
      margin: 5px;
      padding: 5px;
      width: 150px;
      position: relative;
    }
    
    .items {
      width: 175px;
      display: inline-block;
      float: left;
    }
    
    .grocery {
      width: 200px;
      display: inline-block;
      margin-left: 20px;
    }
    
    #sortable {
      border: 1px solid #000;
      min-height: 100px;
    }
    
    .list li span {
      position: absolute;
      right: 4px;
      padding: 2px;
    }
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
    <div class="ui-widget">
      <div class="items list">
        <div class="ui-widget-header">Fruit</div>
        <ul id="FruitCollection" class="fruits">
          <li class="ui-widget-content" data-list="fruits">Apples</li>
          <li class="ui-widget-content" data-list="fruits">Oranges</li>
        </ul>
        <div class="ui-widget-header">Meat</div>
        <ul id="MeatCollection" class="meats">
          <li class="ui-widget-content" data-list="meats">Beef</li>
          <li class="ui-widget-content" data-list="meats">Chicken</li>
          <li class="ui-widget-content" data-list="meats">Pork</li>
        </ul>
        <div class="ui-widget-header">Dairy</div>
        <ul id="DairyCollection" class="dairy">
          <li class="ui-widget-content" data-list="dairy">Cheese</li>
          <li class="ui-widget-content" data-list="dairy">Milk</li>
          <li class="ui-widget-content" data-list="dairy">Sour Cream</li>
          <li class="ui-widget-content" data-list="dairy">Yogurt</li>
        </ul>
      </div>
    
      <div class="grocery list">
        <div class="ui-widget-header">Grocery List</div>
        <ul id="sortable"></ul>
      </div>
    
      <div class="ui-helper-clearfix"></div>
    </div>

    You can make use of a Drag event, but you need a target. The event callback would then perform the same as the Click.