javascript 如何防止拖拽孩子,但允许拖拽父母?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6848140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I prevent drag on a child, but allow drag on the parent?
提问by aepheus
I have a div which the user can drag, inside that div is a span with some text which I want to allow the user to select (thus they cannot drag it). How do I allow the div to drag, but not the span?
我有一个用户可以拖动的 div,在该 div 内是一个带有一些文本的跨度,我希望允许用户选择(因此他们不能拖动它)。我如何允许 div 拖动,而不是跨度?
The dragstart event is on the div.
dragstart 事件在 div 上。
I'm probably overlooking something simple. I tried draggable=true on the div, and draggable=false on the span. That didn't work. Tried returning false on dragstart, that didn't work either.
我可能忽略了一些简单的事情。我在 div 上尝试了 draggable=true ,在 span 上尝试了 draggable=false 。那没有用。尝试在 dragstart 上返回 false,这也不起作用。
dragstart (roughly):
拖动开始(大致):
var jTarget = $(e.target);
if ((jTarget.is('div.header') || (jTarget.parents('div.header'))
&& !jTarget.is('a, input, span')))
{
e.originalEvent.dataTransfer.setData("Text", "test");
}
else
{
if(e.preventBubble)
e.preventBubble();
if(e.stopPropagation)
e.stopPropagation();
return false;//???
}
The if else portion works as I expect, but I cannot get anything to stop the drag and allow the select.
if else 部分按我的预期工作,但我无法停止拖动并允许选择。
回答by mech
just posting in case someone searches for it with a similar Problem
只是发布以防有人用类似的问题搜索它
element.addEventListener('mousedown', function() { this.parentNode.setAttribute("draggable", false); });
element.addEventListener('mouseup', function() { this.parentNode.setAttribute("draggable", true); });
worked for me
对我来说有效
回答by Blixt
If you want to truly cancel out the drag and make it unnoticeable to parent drag handlers, you need to both preventDefault
and stopPropagation
:
如果您想真正取消拖动并使父拖动处理程序不明显,您需要同时执行preventDefault
和stopPropagation
:
<div draggable="true" ondragstart="console.log('dragging')">
<span>Drag me! :)</span>
<input draggable="true"
ondragstart="event.preventDefault();
event.stopPropagation();"
value="Don't drag me :(">
</div>
Without the stopPropagation
, the parent ondragstart
will still be called even if the default behavior will be prevented (event.defaultPrevented == true
). If you have code in that handler that doesn't handle this case, you may see subtle bugs.
如果没有stopPropagation
,ondragstart
即使默认行为将被阻止 ( event.defaultPrevented == true
) ,父项仍将被调用。如果该处理程序中有不处理这种情况的代码,您可能会看到细微的错误。
You can of course put the JavaScript above inside element.addEventListener('dragstart', ...)
too.
你当然也可以把上面的 JavaScript 放在里面element.addEventListener('dragstart', ...)
。
回答by shuji
You can change the child element to draggable and prevent default when ondragstart, this will leave the regular behavior on the child element and the parent will still be draggable
您可以在 ondragstart 时将子元素更改为可拖动并防止默认,这将保留子元素上的常规行为,而父元素仍可拖动
function drag(e){ if(e.target.type=="range")e.preventDefault();/*rest of your code*/ }
html:
html:
<input type="range" draggable="true" ondragstart="drag(event)">
回答by Rob Middleton
Put a mousedown handler on the span and stop the event propagation there.
在 span 上放置一个 mousedown 处理程序并在那里停止事件传播。
回答by CyberNerd
I was inspired by a few of the answers here and I think I came up with the cleanest and most reusable solution. I use a mouse down event to check if the element should be draggable or not. I do this by verifying if it has a specific class name that I only assign to draggable elements. On the mouse up event, I go through all of the elements with that class tag and set their draggable values back to true.
我受到这里的一些答案的启发,我想我想出了最干净和最可重用的解决方案。我使用鼠标按下事件来检查元素是否应该是可拖动的。我通过验证它是否具有我只分配给可拖动元素的特定类名来做到这一点。在鼠标松开事件中,我遍历所有带有该类标记的元素,并将它们的可拖动值设置回 true。
This can break if the input node is a deep child of the draggable div, but then you can use the same algorithm as in the mouse up event and set all of the values to false.
如果输入节点是可拖动 div 的深子节点,这可能会中断,但是您可以使用与鼠标向上事件相同的算法并将所有值设置为 false。
document.addEventListener('mousedown', function (event) {
var clickedElem = event.target;
if(!clickedElem.classList.contains("drop_content")){
clickedElem.parentElement.setAttribute("draggable",false);
}
}, false);
document.addEventListener('mouseup', function () {
var boxes = document.querySelectorAll(".drop_content");
for(var i = 0; i < boxes.length; i++){
boxes[i].setAttribute("draggable",true);
}
}, false);
div{
display:block;
background: black;
padding: 5px;
margin: 2px;
}
<html>
<body>
<div class="drop_content" draggable="true">
<input value="Can't drag me">
</div>
<div class="drop_content" draggable="true">
<input value="Can't drag me either">
</div>
</body>
</html>
回答by Todd Sjolander
In my application, I was unable to get any of the other solutions listed here to work. This is what worked for me:
在我的应用程序中,我无法使此处列出的任何其他解决方案起作用。这对我有用:
ondragstart="event.preventDefault();" draggable="false"
In my specific case, it was a text input inside a div.
在我的特定情况下,它是一个 div 内的文本输入。