如何使用 window 叠加层和多个拖放区处理文件拖放?
How can I handle File drag and drop with a window overlay and multiple drop zones?
我希望能够检测到用户何时将文件拖入 window 并在整个应用程序上弹出一个覆盖层,显示用户可以将文件上传到的各个文件夹。
到目前为止,我明白我可以收听 "dragenter" 的 window 并显示我的叠加层,收听 "dragleave" 的叠加层以隐藏它,但是问题似乎是在拖放区上拖动会导致覆盖层的 dragleave 事件触发,这使得覆盖层隐藏(这使得 window dragenter 事件显示覆盖层,等等)。
我正在为我的文件夹放置区使用 Dropzone.js。我环顾四周发现了与我类似的问题,但是 none 解决了这个问题。
编辑:我在 Whosebug 的其他地方找到了(某种)解决方案:jQuery Drag-and-Drop Flickering on Hover (Webkit only)
解决方案是检查 dragleave 上的事件,如果 pageX 和 pageY 均为 0,则表示 dragleave 是因为用户离开了 window,而不是拖过其中一个拖放区.
dragleave
事件的触发速度比我们想象的要快,因此我们可以延迟该过程。
Dropzone.autoDiscover = false;
$("div#upload").dropzone({
url: "upload.php",
addRemoveLinks:true,
paramName:"composeUpload",
init: function() {
myDropZone = this;
this.on('dragover', function(e,xhr,formData){
$('.overlay').fadeIn();
stopLoading(); //stops local file opens
return false;
});
this.on('dragleave', function(e,xhr,formData){
setTimeout(function(){
$('.overlay').fadeIn();
},8000);
});
}
});
如果您将文件放在空白 div 或覆盖层上,浏览器将在本地打开文件,因此我们必须停止默认设置
function stopLoading(){
window.addEventListener("dragover",function(e){
e = e || event;
e.preventDefault();
},false);
window.addEventListener("drop",function(e){
e = e || event;
e.preventDefault();
},false);
}
我不认为这就是您要找的答案,但它肯定会给您 idea.thanks。
在这种特定情况下(在全屏覆盖层中使用 Dropzone 实例,该覆盖层仅在拖动文件时可见,并且您只希望用户将文件拖放到拖放区而不是整个覆盖层),这就是我要解决的问题问题。
- 在 window 上收听 "dragenter"
- 如果事件 dataTransfer 对象有一个包含 1 个项目的 types 数组,并且 types[0] == "Files" 则显示叠加层(这样我们就不会显示叠加层,如果正在显示类似文本的内容拖)
- 在叠加层上收听 "dragleave"
- 如果 dragleave 事件 pageX 和 pageY 都是 0,那么用户拖出了文档,我们应该隐藏叠加层,否则他们拖过其中一个拖放区
- 在叠加层上收听 "dragover"
- 如果屏幕上有任何 class 为 "dz-drag-hover" 的元素,则将事件 dataTransfer.dropEffect 设置为 "copy",因为我们将鼠标悬停在 dropzone
- 否则将事件 dataTransfer.dropEffect 设置为 "none" 和 preventDefault()
以上是一些未经测试的javascript:
function handleDragEnter( e ) {
// make sure we're dragging a file
var dt = ( e && e.dataTransfer );
var isFile = ( dt && dt.types && dt.types.length == 1 && dt.types[0] == "Files" );
if ( isFile ) {
// and, if so, show the overlay
showOverlay();
}
}
function handleDragLeave( e ) {
// was our dragleave off the page?
if ( e && e.pageX == 0 && e.pageY == 0 ) {
// then hide the overlay
hideOverlay();
}
}
function handleDragOver(e) {
// look for any dropzones being hovered
var isHovering = document.getElementsByClassName( "dz-drag-hover" ).length > 0;
if ( isHovering ) {
// found some? then we're over a dropzone and want to allow dropping
e.dataTransfer.dropEffect = 'copy';
} else {
// we're just on the overlay. don't allow dropping.
e.dataTransfer.dropEffect = 'none';
e.preventDefault();
}
}
function showOverlay() {
// only show the overlay if it's not already shown (can prevent flickering)
if ( getComputedStyle(overlay, null).display == "none" )
overlay.style.display = "block";
}
}
function hideOverlay() {
overlay.style.display = "none";
}
// listen to dragenter on the window for obvious reasons
window.addEventListener("dragenter", handleDragEnter);
// our fullscreen overlay will cover up the window, so we need to listen to it for dragleave events
overlay.addEventListener("dragleave", handleDragLeave);
// same thing for dragover
overlay.addEventListener("dragover", handleDragOver);
我希望能够检测到用户何时将文件拖入 window 并在整个应用程序上弹出一个覆盖层,显示用户可以将文件上传到的各个文件夹。
到目前为止,我明白我可以收听 "dragenter" 的 window 并显示我的叠加层,收听 "dragleave" 的叠加层以隐藏它,但是问题似乎是在拖放区上拖动会导致覆盖层的 dragleave 事件触发,这使得覆盖层隐藏(这使得 window dragenter 事件显示覆盖层,等等)。
我正在为我的文件夹放置区使用 Dropzone.js。我环顾四周发现了与我类似的问题,但是 none 解决了这个问题。
编辑:我在 Whosebug 的其他地方找到了(某种)解决方案:jQuery Drag-and-Drop Flickering on Hover (Webkit only)
解决方案是检查 dragleave 上的事件,如果 pageX 和 pageY 均为 0,则表示 dragleave 是因为用户离开了 window,而不是拖过其中一个拖放区.
dragleave
事件的触发速度比我们想象的要快,因此我们可以延迟该过程。
Dropzone.autoDiscover = false;
$("div#upload").dropzone({
url: "upload.php",
addRemoveLinks:true,
paramName:"composeUpload",
init: function() {
myDropZone = this;
this.on('dragover', function(e,xhr,formData){
$('.overlay').fadeIn();
stopLoading(); //stops local file opens
return false;
});
this.on('dragleave', function(e,xhr,formData){
setTimeout(function(){
$('.overlay').fadeIn();
},8000);
});
}
});
如果您将文件放在空白 div 或覆盖层上,浏览器将在本地打开文件,因此我们必须停止默认设置
function stopLoading(){
window.addEventListener("dragover",function(e){
e = e || event;
e.preventDefault();
},false);
window.addEventListener("drop",function(e){
e = e || event;
e.preventDefault();
},false);
}
我不认为这就是您要找的答案,但它肯定会给您 idea.thanks。
在这种特定情况下(在全屏覆盖层中使用 Dropzone 实例,该覆盖层仅在拖动文件时可见,并且您只希望用户将文件拖放到拖放区而不是整个覆盖层),这就是我要解决的问题问题。
- 在 window 上收听 "dragenter"
- 如果事件 dataTransfer 对象有一个包含 1 个项目的 types 数组,并且 types[0] == "Files" 则显示叠加层(这样我们就不会显示叠加层,如果正在显示类似文本的内容拖)
- 在叠加层上收听 "dragleave"
- 如果 dragleave 事件 pageX 和 pageY 都是 0,那么用户拖出了文档,我们应该隐藏叠加层,否则他们拖过其中一个拖放区
- 在叠加层上收听 "dragover"
- 如果屏幕上有任何 class 为 "dz-drag-hover" 的元素,则将事件 dataTransfer.dropEffect 设置为 "copy",因为我们将鼠标悬停在 dropzone
- 否则将事件 dataTransfer.dropEffect 设置为 "none" 和 preventDefault()
以上是一些未经测试的javascript:
function handleDragEnter( e ) {
// make sure we're dragging a file
var dt = ( e && e.dataTransfer );
var isFile = ( dt && dt.types && dt.types.length == 1 && dt.types[0] == "Files" );
if ( isFile ) {
// and, if so, show the overlay
showOverlay();
}
}
function handleDragLeave( e ) {
// was our dragleave off the page?
if ( e && e.pageX == 0 && e.pageY == 0 ) {
// then hide the overlay
hideOverlay();
}
}
function handleDragOver(e) {
// look for any dropzones being hovered
var isHovering = document.getElementsByClassName( "dz-drag-hover" ).length > 0;
if ( isHovering ) {
// found some? then we're over a dropzone and want to allow dropping
e.dataTransfer.dropEffect = 'copy';
} else {
// we're just on the overlay. don't allow dropping.
e.dataTransfer.dropEffect = 'none';
e.preventDefault();
}
}
function showOverlay() {
// only show the overlay if it's not already shown (can prevent flickering)
if ( getComputedStyle(overlay, null).display == "none" )
overlay.style.display = "block";
}
}
function hideOverlay() {
overlay.style.display = "none";
}
// listen to dragenter on the window for obvious reasons
window.addEventListener("dragenter", handleDragEnter);
// our fullscreen overlay will cover up the window, so we need to listen to it for dragleave events
overlay.addEventListener("dragleave", handleDragLeave);
// same thing for dragover
overlay.addEventListener("dragover", handleDragOver);