HTML5 поведение перетаскивания - PullRequest
13 голосов
/ 20 марта 2011

Я широко использую встроенную в HTML5 функцию перетаскивания, и она почти полностью ведет себя сама, за одним небольшим исключением.

Я пытаюсь выделить свои дропзоны, когда что-либо перетаскивается по странице,Первоначально я пытался добиться этого, помещая слушатели jQuery в тело документа, например:

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

с помощью lightdz () и dimdz (), изменяя свойство стиля background-color всех dropzones на странице, чтобы сделатьони выделяются.Это не сработало.Всякий раз, когда перетаскиваемый объект входит в дочерний элемент на странице (например, контейнер div), слушатель помечает это как событие dragleave и затемняет dropzones.

Я справился с этим, применив слушателя ко всем видимымэлементы на странице, а не просто тело.Иногда на дропзонах было небольшое видимое мерцание, когда оно пересекало границу между одним элементом и другим, но это выглядело нормально.

В любом случае, теперь я изменил lightdz () и dimdz (), чтобы они применялисьбыстрая анимация jQuery fadeTo () для всех не-дропзонов.Это выглядит потрясающе , когда это работает, и делает для пользователей совершенно очевидным, на что они могут, а что нет.Проблема в том, что когда он проходит между границами элементов, он применяет анимацию затухания.Это гораздо более очевидно, чем случайное мерцание цвета фона, особенно если объект очень быстро перетаскивается через несколько границ, он ставит анимацию в очередь и неоднократно приводит к исчезновению и исчезновению страницы.

Дажеесли я не буду беспокоиться о анимации fadeTo () и просто изменю непрозрачность, она будет гораздо более заметной, чем мерцание фона, потому что меняется вся страница, а не только элементы dropzone.

Есть ли способ ссылаться на всю страницу как на единый элемент в целях событий драго и драглэйва?В противном случае, есть ли способ обнаружить падение, которое происходит за пределами окна браузера?Если я пропущу событие dragleave, оно будет выглядеть нормально, но если какой-либо объект перетаскивают через окно браузера, а затем выбрасывают за его пределы, вся страница остается блеклой.

Ответы [ 3 ]

13 голосов
/ 20 марта 2011

Я искренне смущен тем, как легко это было.

$("*: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. Если это произойдет где-либо еще, оно будет иметь ненулевое значение.

2 голосов
/ 20 марта 2011

Возможно, я становлюсь здесь слишком сложным, но я бы сделал что-то вроде этого:

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
    }
});

Кстати, это, вероятно, не сработает сразу, поэтому вам придется немного подправитьработать с вашим кодом.

1 голос
/ 11 декабря 2011

Я попробовал принятое здесь решение, но в итоге использовал setTimeout для решения проблемы.У меня были тонны проблем с контейнером шириной страницы, блокирующим элемент drop, если он был перемещен сверху, и все еще вызывающим проблему, если это элемент 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/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...