jQuery UI 在悬停时添加可放置的事件侦听器
Posted
技术标签:
【中文标题】jQuery UI 在悬停时添加可放置的事件侦听器【英文标题】:jQuery UI add droppable event listener while hovering 【发布时间】:2020-06-03 13:54:45 【问题描述】:我想在拖动一个对象并悬停可放置对象时添加可放置事件侦听器。
这是我的代码:
$('.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');
);
);
而我的 html 是这样的:
<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
?>
我这样做是因为性能问题。我有 3k 可放置的对象,拖动时它会冻结。它必须添加droppable
eventlistener,仅拖动$('.will-be-drag')
对象并悬停$('.will-be-drop')
。
使用此代码它只在悬停时添加而不是在拖动时添加。
我该怎么做?
我想让 javascript 呼吸,设置 3k 可放置对象时已经晚了。只有 30-40 个可拖动元素。这是一张桌子。
【问题讨论】:
$('.will-be-drop').not(this).draggable("disable");
?
不,我想添加仅可放置的悬停项目
你也可以放html代码吗?
好的,我放PHP代码
这不是使函数工作的最佳方式。我会在页面初始化时分配 droppable,然后您可以调整 accept
选项或将它们禁用直到悬停。
【参考方案1】:
这是一个悬停示例:
$(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>
您可以看到,当您将鼠标悬停在 droppable 上时,它会突出显示。当你拖动时,它不会。我怀疑hover
事件不能在持久的mousedown
事件上冒泡。
建议这样做:
$(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>
您还可以使用:visible
或其他一些条件将一些初始化为可丢弃,以减少内存开销。请记住也要销毁它们,否则当用户在拖动时在页面中移动时,您只会堆积内存问题。
【讨论】:
谢谢和抱歉,但性能上没有区别,真的卡住了 @sundowatch 不,我没有用 3000 个项目对其进行测试。我已经更新了我的答案,是的,性能有点慢,但脚本并没有停止。如果页面上有更多元素和其他脚本,则内存资源可能会在某些浏览器上下降到脚本不再响应的状态。如果是这种情况,您可能会考虑根据滚动值初始化和销毁 droppable,并打开其中一组。也许使用:visible
选择器。
是的,这将是一个解决方案,但如果我能够在拖动所有内容时设法获取单元格(将要放置)就可以了
@sundowatch 由于拖动创建的 click-n-hold 活动,某些事件(如悬停)并不总是正确触发。所以鼠标位置或滚动位置条件在拖动过程中可能更好看。
@sundowatch 更新了关于悬停的扩展示例。以上是关于jQuery UI 在悬停时添加可放置的事件侦听器的主要内容,如果未能解决你的问题,请参考以下文章
jQuery UI droppable:悬停时调整元素大小不起作用