悬停时jQuery拖放闪烁(仅限Webkit)

时间:2012-10-18 00:08:35

标签: jquery drag-and-drop

问题

我刚刚完成了一项功能,用户可以将文件拖到浏览器中,然后使用支持的文件上传插件来处理丢弃。

但是,为了向用户提供他们甚至可以放弃事物的提示,我已经实施了一个dragover事件,以显示div类似于“Drop Here”的内容”。反过来,这会隐藏具有“选择文件...”按钮的div,并替换它,直到用户停止拖动。

但是,当我实现这一点时,拖动目标区域会导致闪烁。要明确:

  • div显示“选择文件”界面。
  • 拖动项目(或拖动选定的文字);显示“放在这里”。
  • 项目拖过“Drop here”区域;闪烁开始。

此外:

  • Opera 12或Firefox 16中没有问题。
  • Chrome 23和Safari 5中的问题非常明显。
  • 问题部分存在于IE 9中(IE 10未经测试);它闪烁约5秒钟,然后停止。

jsFiddle

(警告:小提琴很粗糙。)

只需选择一些文字并将其拖到蓝色框上,您就会看到会发生什么;很明显它不应该表现出来的行为。

小提琴中使用的代码

var $dropTarget = $("#container");
$(document).bind("dragover", function(e) {
    if ($dropTarget.hasClass("highlight"))
        return;

    $dropTarget.addClass("highlight");
    $dropTarget.find("[name='drop']").show();
    $dropTarget.find("[name='drag']").hide();
}).bind("dragleave drop", function(e) {
    if (!$dropTarget.hasClass("highlight"))
        return;

    $dropTarget.removeClass("highlight");
    $dropTarget.find("[name='drop']").hide();
    $dropTarget.find("[name='drag']").show();
});​

我的解决方案......?

说实话,我不知道该尝试什么。关于dragoverdragleave的行为没有大量文档,我甚至不知道为什么会这样,所以我甚至无法开始调试它。我觉得dragover应该只发射一次,但即使在屏幕上拖动也只是一遍又一遍地发射它。

我看过谷歌图片和谷歌联系人的拖放行为,但他们的代码完全缩小并且不可读,我甚至找不到任何指定的“拖动”行为。

那么,对这种看似奇怪的行为有什么解决方法吗?如果这是WebKit中的一个错误,我怀疑,是否有一些很好的解决方法和/或黑客我可以使用?

感谢大家的时间!

3 个答案:

答案 0 :(得分:18)

经过一个多小时的淘洗,我找到了someone who had a similar type of issue。似乎Chrome和Safari(至少5)在进入子元素时触发dragleave(并且看似在对该元素进行任何更改时,包括显示/隐藏的子项)。

解决方法是检查pageX中的pageY0是否等于dragleave(但不是 drop

var $dropTarget = $("#container");
$(document).bind("dragenter", function(e) {
    if (e.target == this) {
         return;
    }

    $dropTarget.addClass("highlight");
    $dropTarget.find("[name='drop']").show();
    $dropTarget.find("[name='drag']").hide();
}).bind("dragleave", function(e) {
    if (e.originalEvent.pageX != 0 || e.originalEvent.pageY != 0) {
        return false;
    }

    // Could use .trigger("drop") here.
    $dropTarget.removeClass("highlight");
    $dropTarget.find("[name='drop']").hide();
    $dropTarget.find("[name='drag']").show();
}).bind("drop", function(e) {
    $dropTarget.removeClass("highlight");
    $dropTarget.find("[name='drop']").hide();
    $dropTarget.find("[name='drag']").show();
});​

答案 1 :(得分:0)

我有一些使用拖放文件的项目,在我的项目中也发现了同样的问题, 这是针对您的问题的解决方案,并已针对您的情况进行了测试,那就是100%工作

这是魔术代码:

<style type="text/css">
    .drag * {
        pointer-events: none;
    }
</style>

<div class="drag" id='container'>
<div name='drop' style='display: none;'>DROP HERE</div>
<div name='drag'>DRAG HERE</div>
</div> 

答案 2 :(得分:-1)

我发现使用Eric的解决方案,如果我在使用此解决方案后将Win10谷歌浏览器的屏幕拖到另一个窗口上,它对我来说并不起作用。将条件更改为AND工作。

var $dropTarget = $("#container");
$(document).bind("dragenter", function(e) {
    if (e.target == this) {
         return;
    }

    $dropTarget.addClass("highlight");
    $dropTarget.find("[name='drop']").show();
    $dropTarget.find("[name='drag']").hide();
}).bind("dragleave", function(e) {
    if (e.originalEvent.pageX != 0 || e.originalEvent.pageY != 0) {
        return false;
    }

    // Could use .trigger("drop") here.
    $dropTarget.removeClass("highlight");
    $dropTarget.find("[name='drop']").hide();
    $dropTarget.find("[name='drag']").show();
}).bind("drop", function(e) {
    $dropTarget.removeClass("highlight");
    $dropTarget.find("[name='drop']").hide();
    $dropTarget.find("[name='drag']").show();
});​