HTML5拖动;放弃行为

时间:2011-03-20 16:54:22

标签: javascript jquery html5 drag-and-drop

我正在大量使用HTML5本机拖放功能。只有一个小例外,它几乎完全表现出来了。

当我在页面上拖动任何内容时,我正在尝试突出显示我的下拉区域。我最初试图通过在文档体上放置jQuery监听器来实现这一点,如下所示:

$("body").live('dragover',function(event){lightdz(event)});
$("body").live('dragexit dragleave drop',function(event){dimdz(event)});

使用lightdz()和dimdz()更改页面上所有dropzones的背景颜色样式属性,使它们脱颖而出。这没用。每当被拖动的对象进入页面上的子元素(如div容器)时,侦听器就会将其标记为dragleave事件并使dropzones变暗。

我通过将侦听器应用于页面上的所有可见元素而不仅仅是正文来解决这个问题。当它跨越一个元素和另一个元素之间的边界时,它们偶尔会出现轻微的可见闪烁,但它看起来很好。

无论如何,现在我已经改变了lightdz()和dimdz(),以便他们将快速jQuery fadeTo()动画应用于所有非dropzones。当它工作时,它看起来很棒很棒,并使用户非常清楚他们可以做什么,不能放弃。麻烦的是当它在元素边界之间传递时,它应用淡入淡出动画。这比背景颜色的偶然闪烁要明显得多,特别是因为如果对象被快速拖过多个边界,它会对动画进行排队并使页面反复淡入淡出。

即使我不打扰fadeTo()动画,只是改变不透明度,它比背景颜色闪烁更明显,因为整个页面改变而不仅仅是dropzone元素。

为了dragover和dragleave事件的目的,有没有办法将整个页面作为单个元素引用?如果失败了,有没有办法检测在浏览器窗口之外发生的丢弃?如果我跳过dragleave事件,它看起来很好,但如果任何对象被拖过浏览器窗口然后掉到它外面,整个页面都会褪色。

3 个答案:

答案 0 :(得分:13)

我真的很尴尬,这是多么容易。

$("*:visible").live('dragenter dragover',function(event){lightdz(event)});

$("#page").live('dragleave dragexit',function(event)
{
    if(event.pageX == "0")
       dimdz(event);
});

$("*:visible").live('drop',function(event){dimdz(event)});

#page是一个页面范围的容器。如果dragleave事件将拖动的对象移到浏览器窗口之外,则event.pageX的值为0.如果它在其他任何地方发生,则它将具有非零值。

答案 1 :(得分:2)

我可能会变得过于复杂,但我会这样做:

var draggingFile = false;
var event2;

//elements with the class hotspots are OK
var hotspots = $(".hotspots");

//Handlers on the body for drag start & stop
$("body").live("dragover", function(event){ draggingFile = true; event2 = event; });
$("body").live("dragexit dragleave drop", function(event){ draggingFile = false; event2 = event; });

//Function checks to see if file is being dragged over an OK hotspot regardless of other elements infront
var isTargetOK = function(x, y){
    hotspots.each(function(i, el){
        el2 = $(el);
        var pos = el2.offset();
        if(x => pos.left && x <= pos.left+el2.width() && y => pos.top && y <= post.top+el2.height()){
            return true;
        }
    });
    return false;
};

//Mousemove handler on body
$("body").mousemove(function(e){
    //if user is dragging a file
    if(draggingFile){
        //Check to see if this is an OK element with mouse X & Y
        if(isOKTarget(e.pageX, e.pageY)){
            //Light em' up!
            lightdz(event2);
        } else { /* Fade em' :( */ dimdz(event2); }
    } else {
        dimdz(); //Having no parematers means just makes sure hotspots are off
    }
});
顺便说一句,这可能不会直接起作用,所以你必须稍微调整一下才能使用你的代码。

答案 2 :(得分:1)

我在这里尝试了接受的解决方案,但最终使用setTimeout来克服这个问题。如果页面范围的容器在顶部浮动,我会遇到很多麻烦,如果它是drop元素,那么它仍会导致问题。

<body style="border: 1px solid black;">
    <div id="d0" style="border: 1px solid black;">&nbsp;</div>
    <div id="d1" style="border: 1px solid black; display: none; background-color: red;">-&gt; drop here &lt;-</div>
    <div id="d2" style="border: 1px solid black;">&nbsp;</div>
    <div style="float: left;">other element</div>
    <div style="float: left;">&nbsp;-&nbsp;</div>
    <div style="float: left;">another element</div>
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</body>
<script type="text/javascript">
    var resetTimer;

    var f = function(e)
    {
        if (e.type == "dragover")
        {
            e.stopPropagation();
            e.preventDefault();
            if (resetTimer)
            {
                clearTimeout(resetTimer);
            }
            document.getElementById('d1').style.display = '';
        }
        else
        {
            var f = function()
            {
                document.getElementById('d1').style.display = 'none';
            };
            resetTimer = window.setTimeout(f, 25);  
        }
    };

    document.body.addEventListener("dragover", f, true);
    document.body.addEventListener("dragleave", f, true);
    document.getElementById('d1').addEventListener("drop", function(e){ f(); alert('dropped'); }, false);
</script>

如果您只是拨打f();而不是window.setTimeout(f, 250);,则会看到显示和隐藏元素的一些令人讨厌的闪烁。

<强> http://jsfiddle.net/guYWx/