Stack Overflow Asked by Heila Al-Mogren on January 21, 2021
so I’m trying to make a schedule table where lectures can be dragged from a cell to another, unless the new cell already has a lecture, in this case dragging will be rejected. I’m trying to do this by adding and removing class ‘has_lecture’ from the cell to indicate if it should allow moving cells into or not.
Here is my code.. but for some reason the remove class doesn’t work.
$(".draggable").draggable({
revert: 'invalid'
});
$(".droppable").droppable({
accept: function () {
return (!$(this).hasClass('has_lecture'))
},
drop: function (event, ui) {
var $this = $(this);
ui.draggable.position({
my: "center",
at: "center",
of: $this,
using: function (pos) {
$(this).animate(pos, 200, "linear");
}
});
$(this).addClass('has_lecture')
},
out: function () {
// this line doesn't work
$(this).removeClass('has_lecture')
}
});
The accept function runs whenever the draggable moves over the droppable. That means it checks when you are dragging in, and it also checks when you are dragging out. Once you have dropped it in and set the has_lecture
class, your accept function runs as you attempt to drag it out, and since it has the has_lecture
class, it always returns false, and never gives your out
function a chance to run.
So, knowing about this sort of unexpected behavior, the idea is: if the drop zone is empty, it should only accept if it does not have the has_lecture class. But if the dropzone is not empty, it should continue to accept the element that is currently in it. That will allow you to drag it out. So, once you drag an element into the dropzone, store a reference to the element on the dropzone via $(this).data('dropped', ui.draggable)
and now your accept function can check to see if the element you are attempting to drag in or out is the one that has already been dragged in.
(HTML and css added so the snippet will run)
$(function () {
$(".draggable").draggable({
// revert: 'invalid'
});
$(".droppable").droppable({
accept: function (draggable) {
// new code: new accept clause, accept is not has_lecture OR if the element already dragged onto it is the one you are attempting to drag out
return (!$(this).hasClass('has_lecture') || $(this).data('dropped') && $(this).data('dropped').is(draggable))
},
drop: function (event, ui) {
var $this = $(this); // << your existing code
ui.draggable.position({ // << your existing code
my: "center", // << your existing code
at: "center", // << your existing code
of: $this, // << your existing code
using: function (pos) { // << your existing code
$(this).animate(pos, 200, "linear"); // << your existing code
} // << your existing code
}); // << your existing code
$this.addClass('has_lecture'); // << your existing code
// new code: store a reference to the dropped element on the drop zone
$this.data('dropped', ui.draggable)
},
out: function () {
$(this).removeClass('has_lecture'); // << your existing code
// new code: once you have moved it out, then delete the reference to it since your drop zone is now empty again
$(this).data('dropped', null);
}
});
});
.draggable {
width: 90px;
height: 90px;
padding: 0.5em;
float: left;
margin: 10px 10px 10px 0;
border: 1px solid black;
}
.droppable {
width: 120px;
height: 120px;
padding: 0.5em;
float: left;
margin: 10px;
border: 1px solid black;
}
h3 {
clear: left;
}
.has_lecture {
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="draggable" class="ui-widget-content">
<p>Drag me to my target</p>
</div>
<div class="draggable" class="ui-widget-content">
<p>Drag me to my target</p>
</div>
<div class="draggable" class="ui-widget-content">
<p>Drag me to my target</p>
</div>
<div class="droppable" class="ui-widget-header">
<p>Drop here</p>
</div>
Correct answer by chiliNUT on January 21, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP