Multiple select + Multiple Draggable + Multiple Droppable

by Tilwin Joy

HTML

<div id="container">
    <div id="boxA" class="box">
         <h4>box A</h4>

        <div id="A1" class="slot">
            <div id="a1" class="item"></div>
        </div>
        <div id="A2" class="slot">
            <div id="a2" class="item"></div>
        </div>
        <div id="A3" class="slot">
            <div id="a3" class="item"></div>
        </div>
        <div id="A4" class="slot"></div>
        <div id="A5" class="slot"></div>
    </div>
    <div id="boxB" class="box">
         <h4>box B</h4>

        <div id="B1" class="slot"></div>
        <div id="B2" class="slot">
            <div id="b2" class="item"></div>
        </div>
        <div id="B3" class="slot"></div>
        <div id="B4" class="slot"></div>
        <div id="B5" class="slot">
            <div id="b5" class="item"></div>
        </div>
    </div>
</div>

CSS

* {
    margin:0;
    padding:0;
}
.box {
    float: left;
    width: 150px;
    height: 180px;
    text-align: center;
    margin-left: 20px;
    border: 5px solid #999;
}
.slot {
    position:relative;
    width: 120px;
    height: 15px;
    margin-top: 2px;
    margin: 0 auto;
    border: 1px dotted;
}
.item {
    width: 110px;
    height: 14px;
    margin: 0 auto;
    z-index:1;
    background-color: #CCC;
}
.ui-selecting {
    background: #FECA40;
}
.ui-selected {
    background-color: #F90;
}
.green3 {
    background-color: #D9FFE2;
}

JavaScript

$(function () {

    var dragOption = {
        delay: 10,
        distance: 5,
        opacity: 0.45,
        revert: "invalid",
        start: function (event, ui) {
            $(".ui-selected").each(function () {
                $(this).data("original", $(this).position());
            });
        },
        drag: function (event, ui) {
            var offset = ui.position;
            //console.log(ui, this)
            $(".ui-selected").not(this).each(function () {
                var current = $(this).offset(),
                    targetLeft = document.elementFromPoint(current.left - 1, current.top),
                    targetRight = document.elementFromPoint(current.left + $(this).width() + 1, current.top);
                $(this).css({
                    position: "relative",
                    left: offset.left,
                    top: offset.top
                }).data("target", $.unique([targetLeft, targetRight]));
                //console.log($.unique([targetLeft, targetRight]));
            });
        },
        stop: function (event, ui) {
            validate($(".ui-selected").not(ui.draggable));
        }
    }, dropOption = {
        accept: '.item',
        activeClass: "green3",
        greedy: true,
        drop: function (event, ui) {
            console.log("drop")
            if ($(this).is(".slot") && !$(this).has(".item").length) {
                console.log("appending")
                $(this).append(ui.draggable.css({
                    top: 0,
                    left: 0
                }));
            } else {
                console.log("reverting")
                ui.draggable.animate({
                    top: 0,
                    left: 0
                }, "slow");
            }
            validate($(".ui-selected").not(ui.draggable));
        }
    }

    $(".box").selectable({
        filter: ".item",
        start: function (event, ui) {
            $(".ui-selected").draggable("destroy");
        },
        stop:...