Search code examples
jquery-uijquery-ui-sortable

Queries related to jQuery UI Sortable connected list. Clone Item only once


I have two connected lists - Child list and Parent list. Child list will always be a subset of the parent list.

Below are the two requirements for which I need help:

  1. I want to copy data from parent list to child list. Ideally, the item should get cloned when I drag them from parent list to child list. Currently, it is moving the item. Also, one item should be cloned only once. No duplicate allowed in child list.

  2. I have added a delete functionality in the child list. So whenever a new item is added from parent list to child list. It should also have delete functionality. Not sure how to modify the HTML of the newly added item.

Below is the link for the fiddle: https://jsfiddle.net/pdzwyu8r/

Below is my code:

   $( function() {
   $( "#sortable1" ).sortable({
      connectWith: ".connectedSortable",           
      update: function(event, ui) {         
      var productOrder = $(this).sortable('toArray').toString();  
      $("#sort-2").text (productOrder);  
      }           
        }).disableSelection();
  
    
    $( "#sortable2" ).sortable({
      connectWith: ".connectedSortable"            
    }).disableSelection();
    
  } );

I have found a code that clones item only ones but when I integrate it with my code it does not work. Here is the link for that:

Any help appreciated. Thank you in advance for your help.


Solution

  • I was able to solve the issue. Below is fiddler url: https://jsfiddle.net/te9g3vqu/15/

    and here is my code:

    
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>jQuery UI Sortable - Connect lists</title>
    
    </head>
    <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
    <style>
    
         #sortable1, #sortable2 {
        border: 1px solid #eee;
        width: 142px;
        min-height: 20px;
        list-style-type: none;
        margin: 0;
        padding: 5px 0 0 0;
        float: left;
        margin-right: 10px;
        
      }
      #sortable1 li, #sortable2 li {
        margin: 0 5px 5px 5px;
        padding: 5px;
        font-size: 1.2em;
        width: 120px;
      } #sortable1, #sortable2 {
        border: 1px solid #eee;
        width: 142px;
        min-height: 20px;
        list-style-type: none;
        margin: 0;
        padding: 5px 0 0 0;
        float: left;
        margin-right: 10px;
        
      }
      #sortable1 li, #sortable2 li {
        margin: 0 5px 5px 5px;
        padding: 5px;
        font-size: 1.2em;
        width: 120px;
      }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
    
    <body>
     <br>  
       
        <table>
        <tr>
        <td><h1>My Apps</h1></td><td><h1>All Apps</h1></td><td><h1></h1></td>
        </tr>
        <tr>
        <td  style="vertical-align: top;">
    <ul id="sortable1" class="connectedSortable1">
      <li id="1" class="ui-state-default">Item 1</li>
      <li id="2" class="ui-state-default">Item 2</li>
      <li id="3" class="ui-state-default">Item 3</li>
      <li id="4" class="ui-state-default">Item 4</li>
      <li id="5" class="ui-state-default">Item 5</li>
    </ul></td>
        <td>
    <ul id="sortable2" class="connectedSortable2">
      <li id="a" class="ui-state-highlight">Item a</li>
      <li id="b" class="ui-state-highlight">Item b</li>
      <li id="c" class="ui-state-highlight">Item c</li>
      <li id="d" class="ui-state-highlight">Item d</li>
      <li id="e" class="ui-state-highlight">Item e</li>
      <li id="f" class="ui-state-highlight">Item f</li>
      <li id="g" class="ui-state-highlight">Item g</li>
      <li id="h" class="ui-state-highlight">Item h</li>
      <li id="i" class="ui-state-highlight">Item i</li>
      <li id="j" class="ui-state-highlight">Item j</li>
    </ul></td><td style="vertical-align: top;"><h3>Child List: <span id="sort-1"></span></h3>  
    
       <h3>Parent list: <span id="sort-2"></span></h3>  
       
        <!--h3>Deleted list: <span id="sort-3"></span></h3-->  </td>
        </tr>
        </table>
     
    </body>
    <script>
    
       /**
     * Adds a delete button to given item as child element
     */
    function AddDeleteButtonToItem($item) {
        debugger;
      if (!$item.children(".deleteButton").length) {
        //console.log("adding Del button");
        $item.append("<img class='deleteButton' alt='X'>");
      }
    }
    
    /**
     * Adds a delete button to each item of a list and binds event handler
     */
    function AddDeleteButtonToList($list) {
      // Add the button to each existing item of the list
      $list.children("li").each(function(i, item) {
        AddDeleteButtonToItem($(item));
      });
      // bind delegated click event handler for Delete buttons to list:
      $list.on({
        "click": DeleteMyApp
      }, ".deleteButton");
    }
    
    /**
     * Event handler for Delete item button.
     * 'this' is the Element of the Delete button, which must be a child of the item to delete
     */
    function DeleteMyApp() {
    
      var $item = $(this).closest('li');
      var vid = $item.attr('id');
      //console.log("delete id " + vid);
      //the below statement adds the removed app in All Apps
      // $(this).parent().detach().appendTo("#toolbox");
      //save the removed id here
      $item.remove();
      //update the MyApps list after deletion
      var MyAppsSortable = $("#sortable1").sortable('toArray').toString(); 
                //productOrder = $("#sortable1").sortable('toArray').toString(); 
      $("#sort-1").text (MyAppsSortable);  
    }
      
        Array.prototype.remove = function() {
        var what, a = arguments, L = a.length, ax;
        while (L && this.length) {
            what = a[--L];
            while ((ax = this.indexOf(what)) !== -1) {
                this.splice(ax, 1);
            }
        }
        return this;
    };
    
      
      $( function() {
      
       var vdeletedItemsArray = [];
       
        $( "#sortable1" ).sortable({
          connectWith: ".connectedSortable",
          //delay: 50,
          //revert: false,
         // revert: true,
          update: function(event, ui) {         
           //var MyAppsSortable = $(this).sortable('toArray').toString(); 
             //console.log("products: " + productOrder);
         var MyAppsSortable = $("#sortable1").sortable('toArray').toString(); 
                //productOrder = $("#sortable1").sortable('toArray').toString(); 
           $("#sort-1").text (MyAppsSortable);  
           //code to save in User Pref 
                },
            receive: function(event, ui) {
            
             var clazz = ui.item.attr('id');
                //alert($('#sortable1 [id=' + clazz+']').length);
                if($('#sortable1 [id=' + clazz+']').length > 1){ 
                //jquery ui removes ids. thats why we use card
                    $('#sortable1 [id=' + clazz+']:not(:first)').remove();
                    alert('you can not!');            
                }
           // debugger;
           //AddDeleteButtonToItem(ui.item);
           
            //Array of removed items
            var moved = ui.item;
            var vtemp = moved.attr("id")
            for(var i=0;i<vdeletedItemsArray.length;i++)
            {
                vdeletedItemsArray.remove(vtemp);
            }                           
            $("#sort-3").text(vdeletedItemsArray);
        },
        update: function(event, ui){
            // debugger;
           AddDeleteButtonToItem(ui.item);
        }
    
        }).disableSelection();
        
       
         $( "#sortable2" ).sortable({
          connectWith: ".connectedSortable1",
         
           //axis: "x",
          //revert: true,
           helper: "clone",
           revert: "true",
          //delay: 50,
           update: function(event, ui) {         
           var AllAppsSortable = $(this).sortable('toArray').toString();  
           $("#sort-2").text (AllAppsSortable);  
     
           //code to save in User Pref 
                },
           receive: function(event, ui) {
          //AddDeleteButtonToItem(ui.item);
           var moved = ui.item;
            vdeletedItemsArray.push(moved.attr("id"));
           //alert("Moved" + moved.attr("id"));
                       
          //var productOrder = $(this).sortable('toArray').toString();
          $("#sort-3").text(vdeletedItemsArray);
          //console.log("products: " + productOrder);
        }
    
        }).disableSelection();
        
            // Add Delete buttons to existing items of Child List:
           // debugger;
      AddDeleteButtonToList($("#sortable1"));
        
      } );
      
      $("#sortable2 .ui-state-highlight").draggable({
            helper: function(ev, ui) {
              //  debugger;
            //alert($(this).closest('li').outerHTML() + " ASD");
             //console.log("MY------------------------------------------"+$(this) );
             //var temp = $(this).append("<img class='deleteButton' alt='X'>")[0];
             var temp = $(this)[0].outerHTML;
             
             //temp = temp.append("<img class='deleteButton' alt='X'>");
                //return "<span class='helperPick'>"+ $(this).html() +"</span>";
                return temp;
            },
            connectToSortable: "#sortable1"
        });
    
    
    </script>
    </html>
    

    Hope it helps someone in need.

    Special thanks to Martin Lisowski :)