HannahHunt HannahHunt - 4 months ago 28
Javascript Question

jQuery Deny Draggable Elements Already in Droppable

I have some jQuery divs with the droppable class "dropBox"; I want to accept divs with the class "teamBox", but only if they don't already exist in the droppable "dropBox" container. I've tried doing this by using the

over
event for the dropBox, but found that checking if dropBox contained the draggable element always returned true. I also tried placing a condition in the
accept
portion of the dropBox, but I had the same problem. Code for both attempts below. Thanks!

HTML

<div class="panel-heading">Teams</div>
<div class="panel-body teamContainer">
@foreach($teamContent as $teamID => $teamName)
<div id="{{ $teamID }}" class="teamBox">
<h5><b>{{ $teamName }}</b></h5>
</div>
@endforeach
</div>
<div class="panel-heading">Twitter</div>
<div class="panel-body">
@if(!empty($twitterContent))
@foreach($twitterContent as $twitterID => $screenName)
<span class="{{ $twitterID }}">
<h5>{{ '@' . $screenName }}</h5>
</span>
<div id="{{ $twitterID }}" class="dropBox"></div>
@endforeach
@endif
</div>
<div class="panel-heading">Facebook</div>
<div class="panel-body">
@if(!empty($facebookContent))
@foreach($facebookContent as $pageID => $pageName)
<span class="{{ $pageID }}">
<h5>{{ $pageName }}</h5>
</span>
<div id="{{ $pageID }}" class="dropBox"></div>
@endforeach
@endif
</div>


jQuery Attempt Using
over


$(".teamBox").draggable({
helper: 'clone',
zIndex: 1,
});

$(".dropBox").droppable({
accept: '.teamBox',
over: function(event, ui) {
var draggable = ui.draggable;
var over = $(this);
if($(over).find($(draggable).attr('id')))
{
//Always logs as disabling
console.log("Disabling");
$(over).droppable('disable');
}
},
drop: function(event, ui) {
var dropped = ui.draggable;
var droppedOn = $(this);
$(this).append($(dropped).clone());
$(".dropBox .teamBox").addClass("item");
$(".item").removeClass("ui-draggable");
$(".item").draggable({
zIndex: 1,
});
}
});


jQuery Attempt using
accept


$(".teamBox").draggable({
helper: 'clone',
zIndex: 1,
});

$(".dropBox").droppable({
accept: function(draggable) {
if($(this).has($(draggable).attr('id'))) {
//Always returns false
console.log("Returning false");
return false;
}
return true;
},
drop: function(event, ui) {
var dropped = ui.draggable;
var droppedOn = $(this);
$(this).append($(dropped).clone());
$(".dropBox .teamBox").addClass("item");
$(".item").removeClass("ui-draggable");
$(".item").draggable({
zIndex: 1,
});
}
});


EDIT
Ended up coming up with a solution that worked for me. Here's a Fiddle. Keep in mind that I'm using Laravel Spark, so there's Laravel blade syntax within the HTML that doesn't compile correctly in the Fiddle. However, looking at the code may give you an idea of how to create a drag-and-drop system with cloning and denial of duplicated draggable items.

Answer

I would try this in draggable using revert:

$(".teamBox").draggable({
    helper: 'clone',
    zIndex: 1,
    revert: function(){
        return $(".dropBox .teamBox").length ? true : false;
    }
});

Reference: http://api.jqueryui.com/draggable/#option-revert

Whether the element should revert to its start position when dragging stops.

Function: A function to determine whether the element should revert to its start position. The function must return true to revert the element.