Search code examples
jquery-uiduplicatesdraggable

jQuery UI draggable prevent duplicates


I have a list of items on the left that can be dragged into any of the boxes on the right. The items can be in many boxes but should only occur once per box. I am trying to get hold of the ids of the draggable item and compare that against the id's of all the items already in the box, but can't seem to get it right. My code is as follows:

$(".sortable").sortable({
    revert: true,
    connectWith: ".draggable"
});
$(".draggable").draggable({
    connectToSortable: ".sortable",
    helper: "clone",
    revert: "true",
    placeholder: ".droppable-placeholder",
    stop: function(event, ui) {
        //console.dir(ui.helper[0]);

        var listContainer = ui.helper[0].closest('ul');
        if (listContainer) {
        
          console.dir(listContainer);
          listContainer.find('li').each(function() { //This is not right
              var sortableItemId = $(this).attr("id");
              console.dir($(this));
              console.log("sortable item id " + sortableItemId);
          });
        }
    }
});


$("ul, li").disableSelection();
$(".draggable-column, .droppable-column").on("click", ".close-list-item", function(event) {

    event.preventDefault();
    $(this).closest('li').remove();
});
ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    margin-bottom: 0.7em;
    float: left;
}

li {
    margin: 0.5em;
    padding: 0.5em;
    width: 200px;
    border: 1px solid black;
}

.draggable-column {
    height: 100%;
}

.droppable-item {
    padding: 0.5em;
    float: left;
    align-content: space-between;
}

.droppable-item > h3 {
    text-align: center;
}

.sortable {
    width: 230px;
    height: 10em;
    overflow: auto;
    border: 1px solid black;
    background-color: lightgrey;
}

.droppable-placeholder {
    background-color: yellow;
}

.row {
    display: flex;
    /* equal height of the children*/
}

.col {
    flex: 1;
    /* additionally, equal width */
    padding: 1em;
    border: solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<div class="row">
    <div class="col-xs-4 draggable-column">
        <ul class="" id="draggable-column-list">
            <li class="draggable " id="item1">1 Drag me onto item
                <a href="#" class="close-list-item">
                    <i class="fa fa-window-close"></i>
                </a>
            </li>
            <li class="draggable " id="item2">2 Drag me onto item
                <a href="#" class="close-list-item">
                    <i class="fa fa-window-close"></i>
                </a>
            </li>
            <li class="draggable " id="item3">3 Drag me onto item
                <a href="#" class="close-list-item">
                    <i class="fa fa-window-close"></i>
                </a>
            </li>
            <li class="draggable " id="item4">4 Drag me onto item
                <a href="#" class="close-list-item">
                    <i class="fa fa-window-close"></i>
                </a>
            </li>
            <li class="draggable " id="item5">5 Drag me onto item
                <a href="#" class="close-list-item">
                    <i class="fa fa-window-close"></i>
                </a>
            </li>
        </ul>
    </div>

    <div class="col-xs-8 droppable-column">

        <div class="droppable-item">
            <h3>
              Item 1
            </h3>
            <ul class="sortable" id="ul-item1">

            </ul>
        </div>
        <div class="droppable-item">
            <h3 class="">
              Item 2
            </h3>
            <ul class="sortable" id="ul-item2">

            </ul>
        </div>
        <div class="droppable-item">
            <h3>
              Item 3
            </h3>
            <ul class="sortable" id="ul-item3">

            </ul>
        </div>
        <div class="droppable-item">
            <h3>
              Item 4
            </h3>
            <ul class="sortable" id="ul-item4">

            </ul>
        </div>
        <div class="droppable-item">
            <h3>
              Item 5
            </h3>
            <ul class="sortable" id="ul-item5">

            </ul>
        </div>
        <div class="droppable-item">
            <h3>
              Item 6
            </h3>
            <ul class="sortable" id="ul-item6">

            </ul>
        </div>
    </div>

</div>

I am basically trying to stop duplicates occurring in the same box.


Solution

  • So I finally worked out a possible solution although it is not particularly clean:

    $(".sortable").sortable({
        revert: true,
        connectWith: ".draggable"
       
    });
    
    $(".draggable").draggable({
        connectToSortable: ".sortable",
        helper: "clone",
        revert: "true",
        placeholder: ".droppable-placeholder",
        
        stop: function(event, ui) {
            console.log("--start of stop");
            var listContainer = $(ui.helper[0].parentElement);
            var newListId = listContainer.attr("id");
            var draggableId = $(this).attr("id");
            var cloneId = newListId + "-" + draggableId;
            console.log("new list id: " + newListId);
            console.log("draggableId: " + draggableId);
            console.log("cloneId: " + cloneId);
            var itemExists = false;
            $("#"+ newListId).find('li').each(function() {
                var sortableItemId = $(this).attr("id");
                console.log("sortable item id " + sortableItemId);
                if (sortableItemId != undefined && sortableItemId == cloneId) {
                	console.log("***  sortable item already exists");
                	itemExists = true;
                } 
            });
            if (itemExists) {
            	$("#" + cloneId).remove();
            }
            $(ui.helper[0]).attr("id", cloneId);
            
            console.log("--end of stop");
    
        },
    
    });
    
    
    $("ul, li").disableSelection();
    $(".draggable-column, .droppable-column").on("click", ".close-list-item", function(event) {
    
        event.preventDefault();
        $(this).closest('li').remove();
    });
    ul {
        list-style-type: none;
        margin: 0;
        padding: 0;
        margin-bottom: 0.7em;
        float: left;
    }
    
    li {
        margin: 0.5em;
        padding: 0.5em;
        width: 200px;
        border: 1px solid black;
    }
    
    .draggable-column {
        height: 100%;
    }
    
    .droppable-item {
        padding: 0.5em;
        float: left;
        align-content: space-between;
    }
    
    .droppable-item > h3 {
        text-align: center;
    }
    
    .sortable {
        width: 230px;
        height: 10em;
        overflow: auto;
        border: 1px solid black;
        background-color: lightgrey;
    }
    
    .droppable-placeholder {
        background-color: yellow;
    }
    
    .row {
        display: flex;
        /* equal height of the children*/
    }
    
    .col {
        flex: 1;
        /* additionally, equal width */
        padding: 1em;
        border: solid;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
    <div class="row">
        <div class="col-xs-4 draggable-column">
            <ul class="" id="draggable-column-list">
                <li class="draggable " id="item1">1 Drag me onto item
                    <a href="#" class="close-list-item">
                        <i class="fa fa-window-close"></i>
                    </a>
                </li>
                <li class="draggable " id="item2">2 Drag me onto item
                    <a href="#" class="close-list-item">
                        <i class="fa fa-window-close"></i>
                    </a>
                </li>
                <li class="draggable " id="item3">3 Drag me onto item
                    <a href="#" class="close-list-item">
                        <i class="fa fa-window-close"></i>
                    </a>
                </li>
                <li class="draggable " id="item4">4 Drag me onto item
                    <a href="#" class="close-list-item">
                        <i class="fa fa-window-close"></i>
                    </a>
                </li>
                <li class="draggable " id="item5">5 Drag me onto item
                    <a href="#" class="close-list-item">
                        <i class="fa fa-window-close"></i>
                    </a>
                </li>
            </ul>
        </div>
    
        <div class="col-xs-8 droppable-column">
    
            <div class="droppable-item">
                <h3>
                  Item 1
                </h3>
                <ul class="sortable" id="ul-item1">
    
                </ul>
            </div>
            <div class="droppable-item">
                <h3 class="">
                  Item 2
                </h3>
                <ul class="sortable" id="ul-item2">
    
                </ul>
            </div>
            <div class="droppable-item">
                <h3>
                  Item 3
                </h3>
                <ul class="sortable" id="ul-item3">
    
                </ul>
            </div>
            <div class="droppable-item">
                <h3>
                  Item 4
                </h3>
                <ul class="sortable" id="ul-item4">
    
                </ul>
            </div>
            <div class="droppable-item">
                <h3>
                  Item 5
                </h3>
                <ul class="sortable" id="ul-item5">
    
                </ul>
            </div>
            <div class="droppable-item">
                <h3>
                  Item 6
                </h3>
                <ul class="sortable" id="ul-item6">
    
                </ul>
            </div>
        </div>
    
    </div>