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

chhkpiq4  于 2022-12-02  发布在  其他
关注(0)|答案(8)|浏览(354)

我有一个用户可以拖动的div,在这个div里面有一个span,里面有一些我想让用户选择的文本(因此他们不能拖动它)。我如何允许拖动div,而不允许拖动span?
dragstart事件位于div上。
我可能忽略了一些简单的东西。我在div上尝试了draggable=true,在span上尝试了draggable=false。没有成功。在dragstart上尝试了返回false,也没有成功。
拖动启动(粗略):

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;//???
}

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

vohkndzv

vohkndzv1#

如果要真正取消拖动并使父级拖动处理程序不注意到它,则需要同时使用preventDefaultstopPropagation

<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仍然会被调用。如果处理程序中的代码不处理这种情况,您可能会看到细微的错误。
当然,您也可以将上面的JavaScript放在element.addEventListener('dragstart', ...)中。

bvk5enib

bvk5enib2#

只是张贴在万一有人搜索它与类似的问题

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

为我工作

qyswt5oh

qyswt5oh3#

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

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

HTML格式:

<input type="range" draggable="true" ondragstart="drag(event)">
mccptt67

mccptt674#

将mousedown处理程序放在span上,并在那里停止事件传播。

0lvr5msh

0lvr5msh5#

在我的应用程序中,我无法使用这里列出的任何其他解决方案。以下是对我有效的解决方案:

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

在我的具体例子中,它是div中的文本输入。

szqfcxe2

szqfcxe26#

我从这里的一些答案中得到了启发,我认为我想出了最简洁和最可重用的解决方案。我使用鼠标按下事件来检查元素是否应该是可拖动的。我通过验证它是否有一个我只分配给可拖动元素的特定类名来做到这一点。在鼠标抬起事件中,我检查了所有带有该类标记的元素,并将它们的可拖动值设置回true。
如果输入节点是可拖动div的深层子节点,则此操作可能会中断,但您可以使用与mouse up事件中相同的算法,并将所有值设置为false。
第一个

jpfvwuh4

jpfvwuh47#

它看起来像你需要设置一个标志,表明鼠标是否在孩子或没有.这对我来说工作得很好.如果你设置e.preventDefault()没有条件,你会失去可拖动的父母.
HTML格式:

<div draggable="true" ondragstart="dragStart()">
    <span onmouseenter="childMouseEnter()" onmouseleave="childMouseLeave()">Dont 
        Drag
    </span>        
</div>

JavaScript语言:

let mouseOnChild = false
function childMouseEnter(){
    mouseOnChild = true;
}
function childMouseLeave(){
    mouseOnChild = false;
}
function dragStart(e){
    if(!mouseOnChild){
        e.preventDefault();
        e.stopPropagation();
    }
    //other operations....
}
wmomyfyw

wmomyfyw8#

我发现将标志存储为数据属性是一个合理的可接受的解决方法:

export function Draggable(props: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      {...props}
      draggable={true}
      onMouseDown={(event) => {
        props.onMouseDown?.(event);
        const handles = event.currentTarget.querySelectorAll('.drag-handle');
        const target = event.target as HTMLElement;
        const allow = [...handles].map(handle => handle.contains(target)).some(i => i);
        if (allow) {
          event.currentTarget.setAttribute('data-draggable', 'yes');
        } else {
          event.currentTarget.removeAttribute('data-draggable');
        }
      }}
      onDragStart={(event) => {
        props.onDragStart?.(event);
        const allow = event.currentTarget.hasAttribute('data-draggable');
        if (!allow) {
          event.preventDefault();
          event.stopPropagation();
          return;
        }
      }}
    >
      {props.children}
    </div>
  );
}

相关问题