Javascript jQuery dragenter 或 dragover 以包含孩子
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26756176/
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
jQuery dragenter or dragover to include children
提问by JustSteveKing
I am working on an upload script at the moment, and of course it has drag and drop capabilities.
我目前正在编写一个上传脚本,当然它具有拖放功能。
HoweverI am trying to get this to work when I drag a file over my element it adds the class drag-overhowever because my element has children it is constantly firing because it enters and leaves the element.
但是,当我将文件拖到我的元素上时,我试图让它工作,它会添加类拖拽,但是因为我的元素有子元素,它会不断触发,因为它进入和离开元素。
What I want to knowis how can I expand the *dragenter* / *dragover*to include the main elements children also?
我想知道的是如何扩展*dragenter* / *dragover*以包括主要元素儿童?
Here is a trimmed down version of my code (please note I have disabled the file input):
这是我的代码的精简版本(请注意我已禁用文件输入):
$(document).ready(function(){
$(window).on('dragenter', function(){
$(this).preventDefault();
});
$('#drag-and-drop-zone').on('dragenter', function(){
$(this).addClass('drag-over');
});
$('#drag-and-drop-zone').on('dragleave', function(){
$(this).removeClass('drag-over');
});
});
.uploader
{
width: 100%;
background-color: #f9f9f9;
color: #92AAB0;
text-align: center;
vertical-align: middle;
padding: 30px 0px;
margin-bottom: 10px;
border-radius: 5px;
font-size: 200%;
box-shadow: inset 0px 0px 20px #c9afb2;
cursor: default;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.uploader div.or {
font-size: 50%;
font-weight: bold;
color: #C0C0C0;
padding: 10px;
}
.uploader div.browser label {
background-color: #ffffff;
border: 2px solid #f44;
padding: 5px 15px;
color: #f44;
padding: 6px 0px;
font-size: 40%;
font-weight: bold;
cursor: pointer;
border-radius: 2px;
position: relative;
overflow: hidden;
display: block;
width: 300px;
margin: 20px auto 0px auto;
transition: all 0.3s linear 0s;
}
.uploader div.browser span {
cursor: pointer;
}
.uploader div.browser input {
position: absolute;
top: 0;
right: 0;
margin: 0;
border: solid transparent;
border-width: 0 0 100px 200px;
opacity: .0;
filter: alpha(opacity= 0);
direction: ltr;
cursor: pointer;
}
.uploader div.browser label:hover {
background-color: #f44;
color: #fff;
border: 2px solid #fff;
}
.drag-over{
border: 2px solid #00aef0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="uploader" id="drag-and-drop-zone">
<div>Drag & Drop Images Here</div>
<div class="or">-or-</div>
<div class="browser">
<label>
<span>Select Image</span>
<input type="file" title="Click to add Images" accept="image/*" name="files" disabled="true">
</label>
</div>
</div>
回答by JustSteveKing
Solved it!!
解决了!!
It is a simple case of instead on on('dragenter')I needed to use bind('dragover')
这是一个简单的例子,而不是 on ('dragenter')我需要使用bind('dragover')
$(document).ready(function(){
$(window).on('dragenter', function(){
$(this).preventDefault();
});
$('#drag-and-drop-zone').bind('dragover', function(){
$(this).addClass('drag-over');
});
$('#drag-and-drop-zone').bind('dragleave', function(){
$(this).removeClass('drag-over');
});
});
.uploader
{
width: 100%;
background-color: #f9f9f9;
color: #92AAB0;
text-align: center;
vertical-align: middle;
padding: 30px 0px;
margin-bottom: 10px;
border-radius: 5px;
font-size: 200%;
box-shadow: inset 0px 0px 20px #c9afb2;
cursor: default;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.uploader div.or {
font-size: 50%;
font-weight: bold;
color: #C0C0C0;
padding: 10px;
}
.uploader div.browser label {
background-color: #ffffff;
border: 2px solid #f44;
padding: 5px 15px;
color: #f44;
padding: 6px 0px;
font-size: 40%;
font-weight: bold;
cursor: pointer;
border-radius: 2px;
position: relative;
overflow: hidden;
display: block;
width: 300px;
margin: 20px auto 0px auto;
transition: all 0.3s linear 0s;
}
.uploader div.browser span {
cursor: pointer;
}
.uploader div.browser input {
position: absolute;
top: 0;
right: 0;
margin: 0;
border: solid transparent;
border-width: 0 0 100px 200px;
opacity: .0;
filter: alpha(opacity= 0);
direction: ltr;
cursor: pointer;
}
.uploader div.browser label:hover {
background-color: #f44;
color: #fff;
border: 2px solid #fff;
}
.drag-over{
border: 2px solid #00aef0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="uploader" id="drag-and-drop-zone">
<div>Drag & Drop Images Here</div>
<div class="or">-or-</div>
<div class="browser">
<label>
<span>Select Image</span>
<input type="file" title="Click to add Images" accept="image/*" name="files" disabled="true">
</label>
</div>
</div>
回答by Benjamin
Apparently this problem is more recurrent than I thought since I found at least 5 questions associated with the same topic.
显然这个问题比我想象的更经常出现,因为我发现了至少 5 个与同一主题相关的问题。
Unlike "mouseover", the events "dragover" and "dragleave" do not consider the child elements as a whole, so each time the mouse passes over any of the children, "dragleave" will be triggered.
与“mouseover”不同,“dragover”和“dragleave”事件不考虑子元素作为一个整体,所以每次鼠标经过任何一个子元素时,都会触发“dragleave”。
Thinking about the upload of files, I created a widget that allows:
考虑到文件的上传,我创建了一个小部件,它允许:
- Drag and drop desktop files using $ _FILES
- Drag and drop to browser images/elements or url using $ _POST and cURL
- Attach a device file using button using $ _FILES
- Use input to write/paste url images/elements using $ _POST and cURL
- 使用 $_FILES 拖放桌面文件
- 使用 $_POST 和 cURL 拖放到浏览器图像/元素或 url
- 使用 $_FILES 使用按钮附加设备文件
- 使用输入写入/粘贴使用 $_POST 和 cURL 的 url 图像/元素
The problem: As everything, both form inputs and images, are within DIVs children, "dragleave" was triggered even if it did not leave the dashed line. Using the attribute "pointer-events: none" is not an alternative since methods 3 and 4 need to trigger "onchange" events.
问题:由于表单输入和图像的所有内容都在 DIV 子项中,因此即使没有离开虚线也会触发“dragleave”。使用属性“pointer-events: none”不是替代方法,因为方法 3 和 4 需要触发“onchange”事件。
The solution? An overlapping DIV that covers all the drop-container when the mouse enters, and the only one with child elements with "pointer-events: none".
解决方案?当鼠标进入时覆盖所有放置容器的重叠 DIV,并且是唯一一个带有“pointer-events: none”子元素的 DIV。
The structure:
结构:
- div #drop-container: main div, keep all togheter
- div #drop-area: "dragenter" listener and inmediate trigger #drop-pupup
- div #drop-pupup: at same leval as #drop-area, "dragenter", "dragleave" and "drop" listener
- div #drop-container: 主 div,保持所有在一起
- div #drop-area:“dragenter”监听器和中间触发器#drop-pupup
- div #drop-pupup:与#drop-area、“dragenter”、“dragleave”和“drop”监听器处于同一级别
Then, when the mouse enters by dragging an element to #drop-area, inmediatly shows #drop-pupup ahead and successively the events are on this div and not the initial receiver.
然后,当鼠标通过将元素拖动到#drop-area 进入时,会在前面立即显示 #drop-pupup 并且事件在此 div 上而不是初始接收器上。
Here is the JS/jQuery code. I took the liberty to leave the PoC so do not lose all the time I lost.
这是 JS/jQuery 代码。我冒昧地离开了 PoC,所以不要失去我失去的所有时间。
jQuery(document).on('dragover', '#drop-area', function(event) {
event.preventDefault();
event.stopPropagation();
jQuery('#drop-popup').css('display','block');
});
jQuery(document).on('dragover dragleave drop', '#drop-popup', function(event) {
event.preventDefault();
event.stopPropagation();
console.log(event.type);
// layout and drop events
if ( event.type == 'dragover') {
jQuery('#drop-popup').css('display','block');
}
else {
jQuery('#drop-popup').css('display','none');
if ( event.type == 'drop' ) {
// do what you want to do
// for files: use event.originalEvent.dataTransfer.files
// for web dragged elements: use event.originalEvent.dataTransfer.getData('Text') and CURL to capture
}
}
});
body {
background: #ffffff;
margin: 0px;
font-family: sans-serif;
}
#drop-container {
margin: 100px 10%; /* for online testing purposes only */
width: 80%; /* for jsfiddle purposes only */
display: block;
float: left;
overflow: hidden;
box-sizing: content-box;
position: relative; /* needed to use absolute on #drop-popup */
border-radius: 5px;
text-align: center;
cursor: default;
border: 2px dashed #000000;
}
#drop-area {
display: block;
float: left;
padding: 10px;
width: 100%;
}
#drop-popup {
display: none;
box-sizing: content-box;
position: absolute;
width: 100%;
top: 0;
left: 0;
background: linear-gradient(to BOTTOM, rgba(245, 245, 245, 1) , rgba(245, 245, 245, 0));
height: 512px;
padding: 20px;
z-index: 20;
}
#drop-popup > p {
pointer-events: none;
}
<html>
<head>
<title>Drag and Drop</title>
</head>
<body>
<div id="drop-container">
<div id="drop-area">
<p>Child paragraph content inside drop area saying "drop a file or an image in the dashed area"</p>
<div>This is a child div No. 1</div>
<div>This is a child div No. 2</div>
</div>
<div id="drop-popup">
<p>This DIV will cover all childs on main DIV dropover event and current P tag is the only one with CSS "pointer-events: none;"</p>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" type="text/javascript"></script>
</body>
<html>
About jQuery "on", use it with the div id inside on, so you can start event triggers starting "uploading box" hidden.
关于 jQuery “on”,将其与里面的 div id 一起使用,这样您就可以启动事件触发器,开始隐藏“上传框”。
Finally, I preferred to use "dragover" over "dragenter" because it has a small delay (milliseconds) that favors performance (https://developer.mozilla.org/en-US/docs/Web/API/Document/dragover_event).
最后,我更喜欢使用“dragover”而不是“dragenter”,因为它有利于性能的小延迟(毫秒)(https://developer.mozilla.org/en-US/docs/Web/API/Document/dragover_event) .
回答by Gone Coding
You can simply hide elements from the mouse interaction with styling:
您可以简单地隐藏鼠标与样式交互中的元素:
e.g. add this to the child elements:
例如,将其添加到子元素中:
pointer-events: none;
Unfortunately support is not great in IE for this: http://caniuse.com/#feat=pointer-events
不幸的是,IE 对此的支持不是很好:http: //caniuse.com/#feat=pointer-events
回答by Zoltán Süle
I found 2 other working solutions.
我找到了其他 2 个工作解决方案。
It works only if you do not have other controller elements (edit, delete) inside the area, because this solution blocks them too:
仅当您在该区域内没有其他控制器元素(编辑、删除)时才有效,因为此解决方案也会阻止它们:
#drop * {pointer-events: none;}
There is a better solution.
有一个更好的解决方案。
The idea is that you increase a counter every time you enter/hover into/on a new child element and decrease the counter when you leave one of them.
这个想法是每次进入/悬停在新的子元素上时都会增加一个计数器,并在离开其中一个时减少计数器。
$(document).ready(function(){
var dropzoneCounter = 0;
$('#drag-and-drop-zone').on('dragenter', function(){
dropzoneCounter++;
$(this).addClass('drag-over');
});
$('#drag-and-drop-zone').bind('dragleave', function(){
dropzoneCounter--;
if (dropzoneCounter === 0) {
$(this).removeClass('drag-over');
}
});
$('#drag-and-drop-zone').bind('drop', function(){
dropzoneCounter = 0;
$(this).removeClass('drag-over');
});
});


