英文:
Drag and drop, mouseenter triggered on different element
问题
基于我找到的一些示例(不记得是哪个了,抱歉),我创建了一个“看板”板块,可以将人员拖放到不同的区块中。它是一个带有鼠标悬停在人员上时触发的工具提示/弹出窗口的板块。在完成后开始测试时,我注意到有时在放置一个人之后,我会为不同的人获得一个新的弹出窗口。我不明白为什么、怎么、何时会发生这种情况。因此,我尝试将我的项目拆分到下面的示例中,以查看是否可以找出原因。这个示例的行为就像我的项目一样不正常,但在这里我只是记录了mouseenter事件。
有时当我将“Person A”拖动到“Block B”并放下时,示例将在之后记录“Person B”的鼠标悬停事件。虽然这并不总是发生。
对我来说,似乎如果将Person A拖动到Person B上方,那么在Person A被放下后,它将触发Person B的mouseenter事件。但并非总是如此。也许放下的位置很重要。我只是无法确切地找出它发生的时间,但它经常发生。
编辑:对我来说,鼠标位置似乎保持在拖动开始的地方。如果我立刻在放下后将鼠标迅速移出我正在拖动的区块,那么之前的位置将发生mouseenter事件(现在是不同的区块)。
当我拖动和放下时,我只想删除任何mouseenter事件。
HTML:
<div class="container">
<div class="board" id="board">
<div class="block" id="aaa" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Block A</strong>
<div class="person" id="pa" draggable="true" ondragstart="drag(event)"><span>Person A</span></div>
<div class="person" id="pb" draggable="true" ondragstart="drag(event)"><span>Person B</span></div>
<div class="person" id="pc" draggable="true" ondragstart="drag(event)"><span>Person C</span></div>
</div>
<div class="block" id="bbb" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Block B</strong>
</div>
</div>
<textarea id="log" rows="8"></textarea>
</div>
JavaScript:
function drag(ev) {
$("#log").val(""); //在拖动时重置日志
ev.dataTransfer.setData("text", ev.target.id);
}
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.currentTarget.appendChild(document.getElementById(data));
}
$(document).ready(function() {
$(document).on("mouseenter", ".person", function() {
$("#log").val($("#log").val() + "\nHover on " + $(this).text());
});
});
示例链接:https://jsfiddle.net/60jc17hm/
我只是尝试创建一个测试示例,以便可以找出何时发生这种情况。
英文:
Based on some fiddle I found (do not remember which anymore, sorry), I created a "Kanban board" where I can drag and drop persons into different blocks. Its a board with tooltip/popups on the persons which is triggered on mouseenter on the person div. After completing it and starting testing, I noticed that sometimes after dropping a person I would get a new popup for a different person. I could not understand why and how and when. So I tried to strip my project into the fiddle below to see if I could figure out why. The fiddle is misbehaving just like my project, only here I just log the mouseenter event.
Sometimes when I take "Person A" and drag it to "Block B" and drop it the fiddle will log a hover on "Person B" afterwards. This does not happen always, though.
To me it might seem that if dragging Person A over Person B, it will trigger a mouseenter on Person B AFTER Person A is dropped. But not always. Maybe the point of drop is important. I just can't figure out exactly when it happens, but its often.
Edit: to me it seems like the mouse position remains at the point where drag starts. If I immediately after drop move mouse out of the div I'm dragging "real quick", there is a mouseenter on that previous point happening (where now a different div is).
Of course, I just want to remove any mouseenter events when I'm dragging and dropping.
HTML:
<div class="container">
<div class="board" id="board">
<div class="block" id="aaa" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Block A</strong>
<div class="person" id="pa" draggable="true" ondragstart="drag(event)"><span>Person A</span></div>
<div class="person" id="pb" draggable="true" ondragstart="drag(event)"><span>Person B</span></div>
<div class="person" id="pc" draggable="true" ondragstart="drag(event)"><span>Person C</span></div>
</div>
<div class="block" id="bbb" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Block B</strong>
</div>
</div>
<textarea id="log" rows="8"></textarea>
</div>
Javascript:
function drag(ev) {
$("#log").val(""); //reset log on drag
ev.dataTransfer.setData("text", ev.target.id);
}
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.currentTarget.appendChild(document.getElementById(data));
}
$(document).ready(function() {
$(document).on("mouseenter", ".person", function() {
$("#log").val($("#log").val() + "\nHover on " + $(this).text());
});
});
Fiddle: https://jsfiddle.net/60jc17hm/
I've only tried to create a test-fiddle I can use to pinpoint when this happens.
答案1
得分: 0
我想我成功解决了一些问题。
function displayHover(event){
$("#log").val($("#log").val() + "\n鼠标悬停在" + event.target.innerText);
}
$(document).ready(function() {
$(document).on("mouseenter", ".person", displayHover);
var was_dragged = false;
$(document).on("dragend", function(){
$(document).off("mouseenter", ".person", displayHover);
$(document).one("mousemove", function(){
$(document).on("mouseenter", ".person", displayHover);
})
});
});
至少对我有效...
我会尝试解释一下,但我对此还不太了解,所以可能会很糟糕:
我认为问题在于,当你拖动一个对象时,你有一个“新的鼠标”,它可以在对象上拖动,但不能悬停在它们上面...(我猜实际上它更技术性,但作为一个新手,我是这么看的)
所以当拖动停止时(Jquery dragend 事件),鼠标的“旧”实例(对于这种粗俗的说法我很抱歉)位于旧位置(dragstart),悬停在刚刚移动的对象下面的可拖动元素上(在 person A 下面是 person B,一开始),然后移动到放置的位置并悬停在已放置的元素上。所以你在移动 Person A 块后,首先悬停在 Person B 上,然后是 Person A。
因此,我建议在停止拖动操作时禁用 mouseenter 事件,并在鼠标移动时立即重新激活它。
英文:
I think I managed to work something out.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function displayHover(event){
$("#log").val($("#log").val() + "\nHover on " + event.target.innerText);
}
$(document).ready(function() {
$(document).on("mouseenter", ".person", displayHover)
var was_dragged = false;
$(document).on("dragend", function(){
$(document).off("mouseenter", ".person", displayHover)
$(document).one("mousemove", function(){
$(document).on("mouseenter", ".person", displayHover);
})
});
});
<!-- end snippet -->
It worked for me at least...
I will try to explain, but i'm kind of new to it myself so it will probably be terrible :
I think the thing is, when you drag an object, you have like a "new mouse" that can drag over objects but not hover them... (I guess in reality it is more technical but it is how I see it as a newbie)
So when the drag stops (Jquery dragend event), the "old" instance of the mouse (sorry for such vulgarisation) is at the old place (dragstart), hovers over the draggable element below the one you just moved (under person A is person B, at the beginning), then goes to the drop location and hovers the dropped element
So you hover Person B, then person A, after moving the Person A block
So i suggest to disable the mouseenter event when you stop a drag action, and reactivate it as soon as the mouse moves.
答案2
得分: 0
根据@Hordrist的回答,我最终得到了以下内容。在拖动开始时禁用mouseenter触发,然后在拖动结束后鼠标移动后重新初始化它。
function displayHover(event){
$("#log").val($("#log").val() + "\nHover on " + event.target.innerText);
}
function drag(ev) {
$("#log").val(""); //拖动时重置日志
ev.dataTransfer.setData("text", ev.target.id);
$(document).off("mouseenter", ".person");
}
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.currentTarget.appendChild(document.getElementById(data));
}
$(document).ready(function() {
$(document).on("mouseenter", ".person", displayHover);
$(document).on("dragend", function(){
$(document).one("mousemove", function(){
$(document).on("mouseenter", ".person", displayHover);
});
});
});
请注意,我已经将HTML实体代码(如"
)转换为原始的双引号字符。
英文:
Based on @Hordrist answer I ended up with the below. Disable the mouseenter trigger on drag start, and then reinitialize it after mouse moves after drag ends.
function displayHover(event){
$("#log").val($("#log").val() + "\nHover on " + event.target.innerText);
}
function drag(ev) {
$("#log").val(""); //reset log on drag
ev.dataTransfer.setData("text", ev.target.id);
$(document).off("mouseenter", ".person");
}
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.currentTarget.appendChild(document.getElementById(data));
}
$(document).ready(function() {
$(document).on("mouseenter", ".person", displayHover);
$(document).on("dragend", function(){
$(document).one("mousemove", function(){
$(document).on("mouseenter", ".person", displayHover);
});
});
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论