Show overlay on 'dragenter' when dragging a file from desktop to the browser
Asked Answered
V

3

9

i'm trying to achieve the same effect as on imgur.com (drag a file from the desktop to imgur.com and you'll see a cool overlay). already have a working solution thanks to this post: Event propagation, overlay and drag-and-drop events

BUT: i find the solution rather unsatisfying. the problem is $(document).on('dragenter') gets fired multiple times when hovering over child elements. i was looking for an event that gets fired ONCE when i enter the viewport and ONCE when i leave the viewport so i could have a clean $overlay.fadeIn() and .fadeOut() on dragenter and dragleave.

i solved it with a transparent element that fills the whole viewport. i then call dragenter on that transparent element instead of on $(document). with $('*:visible').live('dragenter') i then show the hidden and the real overlay. $('#transparentOverlay').on('dragleave') hides the overlays. pretty hacky but it works (at least in safari/chrome/firefox)

but just the selector $('*:visible').live() gives me a headache...

anyone have a better suggestion?

Vltava answered 9/2, 2012 at 9:31 Comment(0)
S
9

Try it like this, which works well for me. Essentially, it's imitating the dragenter and dragleave events, but only using dragover:

;(function() {
    var isOver = false, interval;

    $(document).on('dragover', function(e) {
        e.preventDefault();

        clearInterval(interval);

        interval = setInterval(function() {
            isOver = false;
            clearInterval(interval);

            /*** callback for onDragLeave ***/
        }, 100);

        if (!isOver) {
            isOver = true;

            /*** callback for onDragEnter ***/
        }
    });
})();
Selfmoving answered 14/2, 2013 at 15:16 Comment(6)
This is the only solution i have found that worked perfectly... im not sure if there will be issues with the setinterval and memory leaking, but so far, its worked perfectly.Extemporaneous
Has somebody found a better solution since this time ?Pyongyang
Why did you write your answer in French in the first place? And then translate it to English?Sweeny
A (slightly) better solution, based on this one, is to activate a setTimeout handler in the dragleave event. Store the timer's return value, and clear it on dragover. I've found that an actual delay is not even necessary, as the dragleave and dragover events are fired at the same time.Barocchio
Posted my version below to clarify.Barocchio
Genius solution. Speeding up the interval time helped me capture the drag better for the edge case in which the mouse passed by too fast.Hypochlorite
B
3

A more lightweight version of the answer above:

;(function() {
    var dragTimeout;

    $(document).on('dragenter', function(e) {
        // dragenter code
    });

    $(document).on('dragleave', function(e) {
        dragTimeout = setTimeout(function() {
            dragTimeout = undefined;
            // your dragleave code
        });
    });

    $(document).on('dragover', function(e) {
        if (dragTimeout) {
            clearTimeout(dragTimeout);
            dragTimeout = undefined;
        }
    });
})();
Barocchio answered 1/9, 2015 at 16:3 Comment(0)
I
2

May need to see more code/errors you're experiencing. Have you tried a simple boolean to check when your event has fired and limit the subsequent events?

var dragging = false;

$(document).on('dragenter', function(){
    if(!dragging){
        //DO SOMETHING
        dragging = true;
    }
});

$(document).on('dragleave', function(){
    if(dragging){
        //DO SOMETHING
        dragging = false;
    }
});
Interrupted answered 9/2, 2012 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.