I want to add droppable event listener while dragging one object and hovering droppable object.
Here is my code:
$('.will-be-drag').draggable({
helper: 'clone',
drag: function (event, ui) {
$('.will-be-drop').hover(function () {
$(this).droppable({
drop: function (event, ui) {
let item = ui.draggable;
console.log(item[0])
item.detach().appendTo($(this));
}
});
}, function () {
$(this).droppable('disable');
});
}
});
And my HTML is like that:
<div class="will-be-drag"></div>
<div class="will-be-drag"></div>
<div class="will-be-drag"></div>
<?php
for($i = 0; $i <= 3000; $i++){
?>
<div class="will-be-drop"></div>
<?php
}
?>
I’m doing that because of performance issues. I have 3k droppable object and it’s freezing while dragging. It must add droppable
eventlistener with only dragging $('.will-be-drag')
object and hovering $('.will-be-drop')
.
With this code It only adds while hover not while dragging.
How can I do it?
I want javascript to breathe, it’s being late when setting 3k droppable objects. There are only 30-40 draggable element. It’s a table.
Here is a Hover example:
$(function() {
$("#draggable").draggable();
$("#droppable").droppable({
drop: function(event, ui) {
$(this)
.find("p")
.html("Dropped!");
}
}).hover(function(e) {
// IN
$(this)
.addClass("ui-state-highlight");
}, function(e) {
// OUT
$(this)
.removeClass("ui-state-highlight");
});
});
#draggable {
width: 100px;
height: 100px;
padding: 0.5em;
float: left;
margin: 10px 10px 10px 0;
}
#droppable {
width: 150px;
height: 150px;
padding: 0.5em;
float: left;
margin: 10px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="draggable" class="ui-widget-content">
<p>Drag me to my target</p>
</div>
<div id="droppable" class="ui-widget-header">
<p>Drop here</p>
</div>
You can see that when you mouse over the droppable, it highlights. When you drag, it doesn’t. I suspect the hover
event cannot bubble up over the persistent mousedown
event.
Would suggest this:
$(function() {
function makeDrops(n) {
var t = $(".ui-widget").eq(1);
for (var i = 1; i <= n; i++) {
$("<div>", {
id: "drop-" + i,
class: "will-be-drop ui-widget-content"
}).appendTo(t);
}
}
function inViewport(element, detectPartial) {
element = $(element);
detectPartial = (!!detectPartial); // if null or undefined, default to false
var viewport = $(window),
vpWidth = viewport.width(),
vpHeight = viewport.height(),
vpTop = viewport.scrollTop(),
vpBottom = vpTop + vpHeight,
vpLeft = viewport.scrollLeft(),
vpRight = vpLeft + vpWidth,
elementOffset = element.offset(),
elementTopArea = elementOffset.top + ((detectPartial) ? element.height() : 0),
elementBottomArea = elementOffset.top + ((detectPartial) ? 0 : element.height()),
elementLeftArea = elementOffset.left + ((detectPartial) ? element.width() : 0),
elementRightArea = elementOffset.left + ((detectPartial) ? 0 : element.width());
return ((elementBottomArea <= vpBottom) && (elementTopArea >= vpTop)) && ((elementRightArea <= vpRight) && (elementLeftArea >= vpLeft));
}
function markVisible(c) {
c.each(function(i, el) {
if (inViewport(el, true)) {
$(el).addClass("visible");
}
});
}
makeDrops(3000);
$(".will-be-drop").droppable({
drop: function(event, ui) {
let item = ui.draggable;
console.log("Drag Item " + item.text().trim() + " dropped to " + $(this).attr("id"));
item.detach().appendTo($(this));
},
over: function() {
$(this).addClass("ui-state-highlight");
},
out: function() {
$(this).removeClass("ui-state-highlight");
}
}).droppable("disable");
$('.will-be-drag').draggable({
helper: 'clone',
start: function(e, ui) {
markVisible($(".will-be-drop"));
$(".will-be-drop.visible").droppable("enable");
},
drag: function(e, ui) {
$(".will-be-drop.visible").droppable("disable").removeClass("visible");
markVisible($(".will-be-drop"));
$(".will-be-drop.visible").droppable("enable");
},
stop: function(e, ui) {
$(".will-be-drop").droppable("disable");
$(".will-be-drop.ui-state-highlight").removeClass("ui-state-highlight");
}
});
});
.will-be-drag {
width: 50px;
height: 50px;
padding: 0.25em;
float: left;
margin: 10px 10px 10px 0;
}
.will-be-drop {
width: 100px;
height: 100px;
padding: 0.25em;
float: left;
margin: 10px;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="ui-widget">
<div class="will-be-drag ui-widget-content">A</div>
<div class="will-be-drag ui-widget-content">B</div>
<div class="will-be-drag ui-widget-content">C</div>
</div>
<div class="ui-widget">
</div>
You can also initialize some as droppable with :visible
or some other condition to reduce memory overhead. Just remember to also destroy them otherwise you will just pile on the memory issue as the user moves through the page while dragging.
Tags: java, javascriptjavascript, jquery, list