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");
}...