Javascript 如何防止拖动子对象,但允许拖动父对象?

Javascript 如何防止拖动子对象,但允许拖动父对象?,javascript,html,drag-and-drop,Javascript,Html,Drag And Drop,我有一个用户可以拖动的div,在这个div中有一个span,其中有一些文本,我想让用户选择(因此他们不能拖动它)。如何允许div拖动,而不允许span拖动 dragstart事件位于div上 我可能忽略了一些简单的事情。我在div上尝试了draggable=true,在span上尝试了draggable=false。那没用。尝试在dragstart上返回false,但也不起作用 dragstart(大致): if-else部分如我所期望的那样工作,但我无法得到任何东西来停止拖动并允许选择。在范围

我有一个用户可以拖动的div,在这个div中有一个span,其中有一些文本,我想让用户选择(因此他们不能拖动它)。如何允许div拖动,而不允许span拖动

dragstart事件位于div上

我可能忽略了一些简单的事情。我在div上尝试了draggable=true,在span上尝试了draggable=false。那没用。尝试在dragstart上返回false,但也不起作用

dragstart(大致):


if-else部分如我所期望的那样工作,但我无法得到任何东西来停止拖动并允许选择。

在范围上放置鼠标向下处理程序,并停止那里的事件传播。

只是发布,以防有人搜索到类似的问题

element.addEventListener('mousedown', function() { this.parentNode.setAttribute("draggable", false); });
element.addEventListener('mouseup', function() { this.parentNode.setAttribute("draggable", true); });

为我工作

您可以将子元素更改为可拖动,并在ondragstart时防止默认值,这将保留子元素上的常规行为,并且父元素仍然可以拖动

function drag(e){ if(e.target.type=="range")e.preventDefault();/*rest of your code*/  }
html:


在我的应用程序中,我无法使用此处列出的任何其他解决方案。这就是我的工作原理:

ondragstart="event.preventDefault();" draggable="false"

在我的特定情况下,它是一个div中的文本输入。

如果您想真正取消拖动并使父拖动处理程序无法注意到它,您需要同时执行
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>

拖我走!:)
如果没有
stopPropagation
,即使默认行为将被阻止(
event.defaultPrevented==true
),仍将调用父级
ondragstart
)。如果处理程序中有不处理这种情况的代码,您可能会看到细微的bug


当然,您可以将上面的JavaScript放入
元素中。addEventListener('dragstart',…)

这里的一些答案启发了我,我认为我找到了最干净、最可重用的解决方案。我使用鼠标按下事件来检查元素是否应该是可拖动的。我通过验证它是否有我只分配给可拖动元素的特定类名来实现这一点。在mouse-up事件中,我使用该类标记遍历所有元素,并将它们的可拖动值设置回true

如果输入节点是可拖动div的深层子节点,则会中断此操作,但是您可以使用与鼠标向上事件相同的算法,并将所有值设置为false

document.addEventListener('mousedown',函数(事件){
var clickedElem=event.target;
如果(!clickedElem.classList.contains(“drop\u content”)){
单击edelem.parentElement.setAttribute(“可拖动”,false);
}
},假);
document.addEventListener('mouseup',function(){
变量框=document.queryselectoral(“.drop_content”);
对于(变量i=0;i
div{
显示:块;
背景:黑色;
填充物:5px;
保证金:2倍;
}


不要认为这是可能的-尽管您可以通过在div中提供一个拖动句柄来解决这个问题,拖动事件可以附加到该句柄,而内部文本可以选择。无法区分单击/拖动移动和单击/拖动高亮显示。它们都只是一个鼠标按下,然后鼠标移动。您的
dragstart
处理程序中有什么代码?请把它添加到你的问题中。@Marc B-我开始认为我可能不得不这么做。但这并不是最理想的,因为我的跨度可能会占用1.5行,而我希望其他0.5行是可拖动的。这很难实现。而且,这个对象是header对象,因此添加另一个header用于拖动是不可能的。经过测试(我有一个类似的问题),至少不会发生拖动,但其他任何事情也不会发生,不可能选择文本,如果对象是contenteditable,则无法设置光标…对我来说很有用!与mousedown处理程序相比,它似乎是“最干净”的解决方案,而mousedown处理程序与拖动事件无关。作为这个解决方案的一个补充,我使用一个单独的函数来取消对任何子元素的拖动,这样实际的拖动函数就不会因为条件而变得杂乱无章!可以称之为dragCancel之类;)一个好的简单的解决方案。“mouseenter”和“mouseleave”事件对我来说效果更好,很难。有趣的是,对我来说,
mouseenter
mouseleave
有效,而
mousedown
/
mouseup
无效。有了这些,我仍然无法在嵌套的
输入中选择文本。无论如何,好主意@mech!在
input
元素上设置您不希望拖动的
draggable=“true”
,这是这个答案的一个微妙但关键的方面,乍看起来有悖直觉,但对于触发输入的
ondragstart
事件至关重要。我只是把它叫做b/c,这是我遗漏的部分,这个答案帮助我找到了,可能也适用于其他人。
ondragstart="event.preventDefault();" draggable="false"
<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>