Search code examples
javascriptdrag-and-drop

js (vanilla) - drop image on element 1 and handle the drop in default file uploader


I am trying to drop an image on image box - but using the drop event I already created for typical file uploader (prevent code duplication).
I have the following HTML:

<div id="Btn" class="btn2">
    <input id="FileUpl" type="file" style="display:none;">
    <img class="fill">
</div>

And the following JS:

let Btn=document.getElementById("Btn");
let FileUpl=document.getElementById("FileUpl"); 

Btn.addEventListener("drop",Go);

function Go(e) { FileUpl.ondrop(e); } // SEE NOTES BELOW

NOTES
The "FileUpl" originally is generated by a function, which attaches to it special handling of dropped file. Hence: I prefer to not duplicate my code there to run in Btn, but to trigger the ondrop event there. However: Seems nothing is being calling...

The drop event passes to FileUpl.ondrop, but somehow is not being processing. While if I would drop directly on FileUpl control (if it would be stand alone one), then it would process the file on drop without any problem.

My question: What is the right way to trigger the handler I have in the control FileUpl...? I am using Vanilla JS (no library)


Solution

  • You need to prevent the default action for dragenter, dragexit, and dragover events, After that you can handle the dropbox with drop event like this:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Test</title>
        
        <style>
            .drop-section {
                display: flex;
                flex-wrap: wrap;
                justify-content: space-between;
            }
    
            .drop-section > * {
                border: 1px solid #eee;
                min-width: 450px;
                min-height: 450px;
                padding: 30px;
                line-height: 450px;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <section class="drop-section">
            <div class="drop-section__area">
                Drop your image here!
            </div>
        </section>
        
        <script>
            let dropArea = document.querySelector(".drop-section__area");
    
            // preventDefault and stopPropagation with some style
            function dragHandler(e) {
                e.preventDefault();
                e.stopPropagation();
                dropArea.style.background = "#f9f9f9";
                dropArea.style.opacity = ".5";
            };
    
            dropArea.addEventListener("dragenter", dragHandler);
            dropArea.addEventListener("dragexit", dragHandler);
            dropArea.addEventListener("dragover", dragHandler);
    
            // handle the drop event
            function drop(e) {
                e.stopPropagation();
                e.preventDefault();
                dropArea.style.background = "unset";
                dropArea.style.opacity = "1";
                var [file] = e.dataTransfer.files;
                console.log(file.name);
            };
    
            dropArea.addEventListener("drop", drop);
        </script>
    </body>
    </html>

    Read more about DataTransfer from here