JSFiddle - React, Tailwind, and code Playground

by tunafish

HTML

<div class="page">

<div class="container">
    <p>Album</p>
    <ul class="listing album">
        <li id="li-1"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2008/04/ireland-flag.gif" /></li>
        <li id="li-2"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2007/06/austria-flag.gif" /></li>
        <li id="li-3"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2007/06/puerto-rico-falg.gif" /></li>
        <li id="li-4"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2007/06/japan-flag.gif" /></li>
        <li id="li-5"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2007/06/bolivia-flag.gif" /></li>
    </ul>
</div>
    
<div style="clear:both;"></div>
    
<div class="container">
    <p>Favorites</p>    
    <ul class="favorites album">
        <li id="fli-1"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2008/04/ireland-flag.gif" /></li>
        <li id="fli-2"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2007/06/austria-flag.gif" /></li>
        <li id="fli-3"><img src="http://www.hamovhotov.com/ratemycountry/wp-content/uploads/2007/06/kazakhstan-flag.gif" /></li>
    </ul>
</div>

</div>

CSS

.page { width: 410px; padding: 20px; margin: 0 auto; background: darkgray; }
h2 { margin: 0; padding: 0; }

.album { list-style: none; overflow: hidden; 
    width: 410px; margin: 0; padding: 0; padding-top: 5px;
    background: gray; 
} 
.listing { margin-bottom: 10px; }
.album li { float: left; outline: none;
    width: 120px; height: 80px; margin: 0 0 5px 5px; padding: 5px;
    background: #222222;
 }
li.placeholder { background: lightgray; }

JavaScript

$("ul, li").disableSelection();

$(".album, .favorites").sortable({
    connectWith: ".album, .favorites",
    placeholder: "placeholder", 
    forcePlaceholderSize: true, 
    revert: 300,
    helper: "clone",
    stop: uiStop,
    receive: uiReceive,
    over: uiOver
});


$(".album li").mousedown(mStart);

var iSender, iTarget, iIndex, iId, iSrc, iCopy;
var overCount = 0;

/* everything starts here */
function mStart() {
    // remove any remaining .copy classes
    $(iSender + " li").removeClass("copy");
    // set vars
    if ($(this).parent().hasClass("listing")) { 
        iSender = ".listing"; 
        iTarget = ".favorites"; 
    } 
    else { 
        iSender = ".favorites"; 
        iTarget = ".listing"; 
    }
    iIndex = $(this).index();
    iId = $(this).attr("id");
    iSrc = $(this).find("img").attr("src");    
    iCopy = $(iTarget + " li img[src*='" + iSrc + "']").length > 0; // boolean, true if there is allready a copy in the target list    
    // disable target if item is allready in there    
    if (iCopy) { 
        $(iTarget).css("opacity","0.5").sortable("disable"); 
    }
}

/* when sorting has stopped */
function uiStop(event, ui) {
    // enable target
    $(iTarget).css("opacity","1.0").sortable("enable");
    // reset item vars
    iSender = iTarget = iIndex = iId = iSrc = iCopy = undefined;
    overCount = 0;
    // reinit mousedown, live() did not work to disable
    $(".album li").mousedown(mStart);
}

/* rolling over the receiver - over, out, over etc. */
function uiOver(event, ui) {
    // only if item in not allready in the target
    if (!iCopy) {                    
        // counter for over/out (numbers even/uneven)
        overCount++;
        // if even [over], clone to original index in sender, show and fadein (sortables hides it)
        if (overCount%2) {
            if (iIndex == 0) { 
                ui.item.clone().addClass("copy").attr("id", iId).prependTo(iSender).fadeIn("slow"); 
            } 
           ...