简体   繁体   English

事件传播、覆盖和拖放事件

[英]Event propagation, overlay and drag-and-drop events

I want to overlay a div over the viewport when the user drags a file onto the window.当用户将文件拖到窗口上时,我想在视口上覆盖一个 div。

However, I'm having trouble with the event propagation.但是,我在事件传播方面遇到了麻烦。 When I set the overlay to display: block it appears to fire off a dragleave event and then another dragenter and then another dragleave again, so it's always in a post-dragleave state.当我将叠加层设置为display: block时,它似乎会触发一个dragleave事件,然后是另一个dragenter ,然后是另一个dragleave ,因此它始终处于 post-dragleave 状态。 Of course I call e.stopPropagation() and e.preventDefault() on the event object, but it doesn't seem to make a difference.当然,我在事件对象上调用e.stopPropagation()e.preventDefault() ,但这似乎没有什么区别。

The console.log() output when you drag something over the window:当您在窗口上拖动某些东西时, console.log()输出:

dragenter拖拉机
dragenter拖拉机
dragleave拖离
dragenter拖拉机
dragleave拖离

The css.的CSS。 #overlay is set to display: none by default, but will show if body has the dragenter class: #overlay设置为display: none默认情况下,但会显示body是否有dragenter类:

    body {
        position: absolute;
        height: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: 0;
        padding: 0;
    }

    #overlay {
        position: absolute;        
        height: auto;
        width: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: url(bg.png) repeat-x top right, url(bg.png) repeat-x bottom left, url(bg.png) repeat-y top right, url(bg.p
ng) repeat-y bottom left;
        display: none;
    }

    body.dragenter #overlay {
        display: block;
    }

The JavaScript; JavaScript; add the 'dragenter' class on dragenter and removes it on dragleave :在 dragenter 上添加 ' dragenter ' 类并在dragleave上删除它:

$(document).on('dragenter', function (e) {
    e.stopPropagation();
    e.preventDefault();
    console.log('dragenter');
    $(document.body).addClass('dragenter');
});

$(document).on('dragleave', function (e) {
    e.stopPropagation();
    e.preventDefault();
    console.log('dragleave';
    $(document.body).removeClass('dragenter');
});

The html:的HTML:

<body>
<div id="overlay">...</div>
...    
</body>

Your overlay takes up the whole document size, when you drag in, it fills up its space and your mouse is effectively taken out of the body and is now over the overlay.您的叠加层占据了整个文档的大小,当您拖入时,它会填满其空间,并且您的鼠标实际上已从正文中取出,现在位于叠加层上方。 This triggers a mouseleave/mouseenter loop.这会触发 mouseleave/mouseenter 循环。 To achieve what you are after, you may want to bind the event to a transparent overlay with a high z-index over the visible overlay which has a lower z-index.为了实现您的目标,您可能希望将事件绑定到具有高 z-index 的透明覆盖层,而不是具有较低 z-index 的可见覆盖层。 This would keep the event in the highest element.这将使事件保持在最高元素中。

Example:例子:

http://jsfiddle.net/scottux/z7yaB/ http://jsfiddle.net/scottux/z7yaB/

Thanks to Scottux, that led me onto the right track.感谢 Scottux,这让我走上了正确的道路。

Only problem was it also covered up the rest of the page, so none of the elements or inputs were clickable.唯一的问题是它也覆盖了页面的其余部分,因此没有任何元素或输入是可点击的。 I had to hide #dragOverlay by default with " display: none " and display it on this event默认情况下,我必须使用“ display: none ”隐藏#dragOverlay 并在此事件中显示它

// Display an overlay when dragging a file over
$('*:visible').live('dragenter', function(e) {
    e.stopPropagation();
    $('body').addClass('drag-enter');
});
    var dropZone = function() {
        var self = this;
        this.eTimestamp = 0;
        this.showDropZone = function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (self.eTimestamp + 300 < e.timeStamp) {
                $("#coverDropZone").show();
                self.eTimestamp = e.timeStamp;
            }
            return false;
        }
        this.hideDropZone = function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (self.eTimestamp + 300 < e.timeStamp) {
                $("#coverDropZone").hide();
                self.eTimestamp = e.timeStamp;
            }
            return false;
        }
        this.showImage = function(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log(e);
            return false;
        }
        document.addEventListener('dragenter', self.showDropZone, false);
        document.addEventListener('dragleave', self.hideDropZone, false);
        document.addEventListener('drop', self.showImage, false);
    }

The simple solution is instead of using dragenter use dragover简单的解决方案是使用dragover而不是使用dragenter

dragover This event is fired as the mouse is moved over an element when a drag is occurring. dragover 发生拖动时,当鼠标移到元素上时会触发此事件。 Much of the time, the operation that occurs during a listener will be the same as the dragenter event.很多时候,在监听器期间发生的操作将与 dragenter 事件相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM