如何实现拖放以便拖动子元素将拖动整个父元素
How to implement drag and drop so dragging child element will drag whole parent element
我正在为 wordpress 开发一个媒体导入插件。我正在尝试实现拖放功能以重新排序用户导入的媒体元素(音频 and/or 图像)。我有一个 <div>
标签(我们将这些称为 media divs),最多可容纳三个其他 <span>
、<img>
, 或 <audio>
标签。所以我将所有已导入的媒体资产显示在一行中,并希望能够拖放以重新排序 media divs。我可以使用 html5 实现基本的拖放操作。我的问题是,现在当我单击 media divs 中的媒体子元素(<audio>
或 <img>
)时,子元素是拖动事件的目标。有什么方法可以将拖动事件的目标重置为父元素,以便我拖动整个 media div 而不仅仅是媒体元素?我研究了 e.stopPropogation()
并阅读了有关冒泡和捕获的内容,但我尝试使用它们的每一种方式都没有解决我的问题。有什么我想念的吗?如果可能,我宁愿避免使用 jQuery 并且绝对不能使用任何库或框架。
TL;DR:单击子元素时,如何使父元素成为拖动事件的目标?
<div class="npr-import-media npr-import-audio npr-import-images" id="media-container">
<div class="npr-import-media-container" draggable="true">
<audio src="<?php echo $audio->format->mp4->{'$text'}; ?>" controls></audio>
<span class="npr-media-delete">X</span>
</div>
<div class="npr-import-image-container npr-import-media-container" draggable="true">
<img class="npr-import-image" src="<?php echo $image->src; ?>" >
<span class="npr-import-image-caption"><?php echo $image->caption->{'$text'} ?></span>
<span class="npr-media-delete">X</span>
</div>
<div class="npr-import-add-media npr-import-media-container">
Add Media+
</div>
</div>
这是我代码的 HTML 部分。最初还有一些 php 功能可以循环遍历原始来源 material 以显示从原始文章导入的所有媒体元素,但我认为没有必要包括它。
您可以将 ondragstart
事件的处理程序设置为 return false,如下所示:
<div class="npr-import-media npr-import-audio npr-import-images" id="media-container">
<div class="npr-import-image-container npr-import-media-container" draggable="true" ondragstart="drag(event)" style="border:1px solid blue;padding:10px;">
<img class="npr-import-image" src="img.jpg" >
<span class="npr-import-image-caption">Caption</span>
<span class="npr-media-delete">X</span>
</div>
<div class="npr-import-add-media npr-import-media-container">
Add Media+
</div>
</div>
<script>
function drag(e) {
console.log(e);
}
var images = document.getElementsByTagName('img');
for(i = 0 ; i < images.length; i++)
images[i].ondragstart = function() { return false; }
</script>
在控制台输出中您可以看到:
>> DragEvent {isTrusted: true, dataTransfer: DataTransfer, screenX: 66, screenY: 161, clientX: 66…}
更新
通过上面的 html 属性或通过代码附加事件侦听器来在父元素上设置拖动事件处理程序,如下所示:
document.getElementById('draggable').addEventListener('dragstart', function(e) {
console.log(e);
});
我遇到了同样的问题,无法解决 img 标签,所以切换到 div。
您可以使用
<div style="background-image: url('img.jpg')"></div>
而不是
<img class="npr-import-image" src="img.jpg" >
我也刚遇到这个问题。我通过简单地向每个子元素添加 draggable="false" 来在没有 javascript 的情况下解决它。
<div class="npr-import-image-container npr-import-media-container" draggable="true" ondragstart="drag(event)" style="border:1px solid blue;padding:10px;">
<img draggable="false" class="npr-import-image" src="img.jpg" >
<span draggable="false" class="npr-import-image-caption">Caption</span>
<span draggable="false" class="npr-media-delete">X</span>
</div>
我遇到过类似的情况。我有一个 parent 和两个 children(夹具和内容),并且需要在拖动夹具时拖动整个 parent,但在拖动内容时不拖动
使 parent 和内容可拖动,但在内容的 ondragstart
中,取消拖动,这样只有当鼠标不在内容中(但在夹具中)时才会开始拖动)
const catchAndPreventDragStartEventGettingToParent = (event) => {
//prevent drag behaviour in content item,
console.log("no dragging");
event.preventDefault();
};
const dragStart = (event) => {
console.log("dragging");
//event.dataTransfer.effectAllowed = "move";
//event.dataTransfer.setData("text/plain", JSON.stringify(data));
};
#parent{
padding: 1rem;
background-color:teal;
}
.gripper{
margin: 1rem;
padding:1rem;
background-color: linen;
}
.content{
margin: 1rem;
padding:1rem;
background-color: pink;
}
<div
id="parent"
draggable = true
ondragstart= "dragStart(event)">
<span class ="gripper">Gripper:</span>
<span
class = "content"
draggable= true
ondragstart="catchAndPreventDragStartEventGettingToParent(event)">
CONTENT
</span>
</div>
也许为时已晚,但我找到了一种简单的方法来获得最接近 parent 的特定 css class.
根据你的例子尝试使用
const handleDragEnter = (e) => {
let desiredTarget = e.target.closest('.npr-import-image-container');
console.log(desiredTarget);
// do stuff...
}
我正在为 wordpress 开发一个媒体导入插件。我正在尝试实现拖放功能以重新排序用户导入的媒体元素(音频 and/or 图像)。我有一个 <div>
标签(我们将这些称为 media divs),最多可容纳三个其他 <span>
、<img>
, 或 <audio>
标签。所以我将所有已导入的媒体资产显示在一行中,并希望能够拖放以重新排序 media divs。我可以使用 html5 实现基本的拖放操作。我的问题是,现在当我单击 media divs 中的媒体子元素(<audio>
或 <img>
)时,子元素是拖动事件的目标。有什么方法可以将拖动事件的目标重置为父元素,以便我拖动整个 media div 而不仅仅是媒体元素?我研究了 e.stopPropogation()
并阅读了有关冒泡和捕获的内容,但我尝试使用它们的每一种方式都没有解决我的问题。有什么我想念的吗?如果可能,我宁愿避免使用 jQuery 并且绝对不能使用任何库或框架。
TL;DR:单击子元素时,如何使父元素成为拖动事件的目标?
<div class="npr-import-media npr-import-audio npr-import-images" id="media-container">
<div class="npr-import-media-container" draggable="true">
<audio src="<?php echo $audio->format->mp4->{'$text'}; ?>" controls></audio>
<span class="npr-media-delete">X</span>
</div>
<div class="npr-import-image-container npr-import-media-container" draggable="true">
<img class="npr-import-image" src="<?php echo $image->src; ?>" >
<span class="npr-import-image-caption"><?php echo $image->caption->{'$text'} ?></span>
<span class="npr-media-delete">X</span>
</div>
<div class="npr-import-add-media npr-import-media-container">
Add Media+
</div>
</div>
这是我代码的 HTML 部分。最初还有一些 php 功能可以循环遍历原始来源 material 以显示从原始文章导入的所有媒体元素,但我认为没有必要包括它。
您可以将 ondragstart
事件的处理程序设置为 return false,如下所示:
<div class="npr-import-media npr-import-audio npr-import-images" id="media-container">
<div class="npr-import-image-container npr-import-media-container" draggable="true" ondragstart="drag(event)" style="border:1px solid blue;padding:10px;">
<img class="npr-import-image" src="img.jpg" >
<span class="npr-import-image-caption">Caption</span>
<span class="npr-media-delete">X</span>
</div>
<div class="npr-import-add-media npr-import-media-container">
Add Media+
</div>
</div>
<script>
function drag(e) {
console.log(e);
}
var images = document.getElementsByTagName('img');
for(i = 0 ; i < images.length; i++)
images[i].ondragstart = function() { return false; }
</script>
在控制台输出中您可以看到:
>> DragEvent {isTrusted: true, dataTransfer: DataTransfer, screenX: 66, screenY: 161, clientX: 66…}
更新 通过上面的 html 属性或通过代码附加事件侦听器来在父元素上设置拖动事件处理程序,如下所示:
document.getElementById('draggable').addEventListener('dragstart', function(e) {
console.log(e);
});
我遇到了同样的问题,无法解决 img 标签,所以切换到 div。
您可以使用
<div style="background-image: url('img.jpg')"></div>
而不是
<img class="npr-import-image" src="img.jpg" >
我也刚遇到这个问题。我通过简单地向每个子元素添加 draggable="false" 来在没有 javascript 的情况下解决它。
<div class="npr-import-image-container npr-import-media-container" draggable="true" ondragstart="drag(event)" style="border:1px solid blue;padding:10px;">
<img draggable="false" class="npr-import-image" src="img.jpg" >
<span draggable="false" class="npr-import-image-caption">Caption</span>
<span draggable="false" class="npr-media-delete">X</span>
</div>
我遇到过类似的情况。我有一个 parent 和两个 children(夹具和内容),并且需要在拖动夹具时拖动整个 parent,但在拖动内容时不拖动
使 parent 和内容可拖动,但在内容的 ondragstart
中,取消拖动,这样只有当鼠标不在内容中(但在夹具中)时才会开始拖动)
const catchAndPreventDragStartEventGettingToParent = (event) => {
//prevent drag behaviour in content item,
console.log("no dragging");
event.preventDefault();
};
const dragStart = (event) => {
console.log("dragging");
//event.dataTransfer.effectAllowed = "move";
//event.dataTransfer.setData("text/plain", JSON.stringify(data));
};
#parent{
padding: 1rem;
background-color:teal;
}
.gripper{
margin: 1rem;
padding:1rem;
background-color: linen;
}
.content{
margin: 1rem;
padding:1rem;
background-color: pink;
}
<div
id="parent"
draggable = true
ondragstart= "dragStart(event)">
<span class ="gripper">Gripper:</span>
<span
class = "content"
draggable= true
ondragstart="catchAndPreventDragStartEventGettingToParent(event)">
CONTENT
</span>
</div>
也许为时已晚,但我找到了一种简单的方法来获得最接近 parent 的特定 css class.
根据你的例子尝试使用
const handleDragEnter = (e) => {
let desiredTarget = e.target.closest('.npr-import-image-container');
console.log(desiredTarget);
// do stuff...
}