JQuery dragenter или dragover для включения детей
Я работаю над загрузкой script на данный момент, и, конечно, у него есть возможности перетаскивания.
Однако Я пытаюсь заставить это работать, когда я перетаскиваю файл поверх своего элемента, он добавляет класс перетаскивания, однако, поскольку у моего элемента есть дети, он постоянно стрельба из-за того, что он входит и покидает элемент.
Что я хочу знать, как я могу расширить *dragenter* / *dragover*
, чтобы включить в нее также основные элементы?
Вот урезанная версия моего кода (обратите внимание, что я отключил ввод файла):
$(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>
Ответы
Ответ 1
Решил его!!
Это простой случай вместо 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>
Ответ 2
По-видимому, эта проблема является более повторяющейся, чем я думал, поскольку я нашел по крайней мере 5 вопросов, связанных с той же темой.
В отличие от "наведения мыши", события "dragover" и "dragleave" не рассматривают дочерние элементы как единое целое, поэтому каждый раз, когда мышь проходит над любым из дочерних элементов, "dragleave" срабатывает.
Думая о загрузке файлов, я создал виджет, который позволяет:
- Перетащите файлы рабочего стола, используя $ _FILES
- Перетащите в браузер изображения/элементы или URL, используя $ _POST и cURL
- Прикрепите файл устройства с помощью кнопки, используя $ _FILES
- Используйте ввод для записи/вставки изображений/элементов URL с помощью $ _POST и cURL
![enter image description here]()
Проблема: поскольку все, как входные данные, так и изображения, находятся внутри дочерних элементов DIV, "dragleave" был запущен, даже если он не покинул пунктирную линию. Использование атрибута "pointer-events: none" не является альтернативой, поскольку методы 3 и 4 должны инициировать события "onchange".
Решение? Перекрывающийся DIV, который покрывает весь drop-контейнер, когда мышь входит, и единственный с дочерними элементами с "pointer-events: none".
Структура:
- div # drop-container: основной div, сохранить все вместе
- div # drop-area: слушатель "dragenter" и промежуточный триггер # drop-pupup
- div # drop-pupup: на том же уровне, что и # drop-area, "dragenter", "dragleave" и "drop" слушатель
Затем, когда мышь входит, перетаскивая элемент в # drop-area, сразу же показывается # drop-pupup вперед и последовательно события находятся в этом div, а не в начальном получателе.
![enter image description here]()
Вот код 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>
Ответ 3
Вы можете просто скрыть элементы от взаимодействия с мышью:
например. добавьте это к дочерним элементам:
pointer-events: none;
К сожалению, поддержка в IE невелика: http://caniuse.com/#feat=pointer-events
Ответ 4
Я нашел 2 других рабочих решения.
Это работает, только если у вас нет других элементов контроллера (edit, delete) внутри области, потому что это решение также блокирует их:
#drop * {pointer-events: none;}
Есть лучшее решение.
Идея состоит в том, что вы увеличиваете счетчик каждый раз, когда вводите/наводите на/на новый дочерний элемент, и уменьшаете счетчик, когда выходите из одного из них.
$(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');
});
});
Ответ 5
Ответ Бенджамина - единственное твердое решение здесь. Выделение прозрачного наложения при dragover
и присоединение к этому наложению событий dragleave
и drop
- единственное решение, найденное среди многих ответов.