# Drag and Drop file upload with Py-Script I've been playing with pyscript and I struggled for a while to find a way to upload a file via drag and drop anywhere on the page. The current implementation of pyscript limits drag and drop to just the input tag. I eventually found you can use javascript to capture the file and save it to a hidden tag on the page and have a delayed EventListener in pyscript to read that tag. ``` <html> <head> <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css"/> <script defer src="https://pyscript.net/alpha/pyscript.js"></script> <script> function preventDefaults (e) { e.preventDefault() e.stopPropagation() } ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { document.addEventListener(eventName, preventDefaults, false) }) document.addEventListener("drop", e => { var file = e.dataTransfer.files[0], reader = new FileReader(); reader.onload = function(event) { var thedata = event.target.result if (thedata !=null){ var encodedString = btoa(thedata) document.getElementById("hiddentext").innerHTML = encodedString } }; reader.readAsText(file); }); </script> </head> <body> <ol> <li> <label for="upload">File Upload:</label> <input type="file" name="upload" id="upload"> </li> </ol> <textarea id="hiddentext" style="display:none;"></textarea> <div id="output"></div> <py-script> import pyodide, js, asyncio, base64 from js import FileReader from pyodide import create_proxy from base64 import b64decode def reader_handler(event): thedata = event.target.result document.getElementById("output").textContent = str(thedata) def upload_handler(event): reader = FileReader.new() reader.onload = create_proxy(reader_handler) reader.readAsText(event.target.files.item(0)) async def drop_handler(event): await asyncio.sleep(0.1) thexml = b64decode(document.getElementById('hiddentext').value).decode("ascii") document.getElementById("output").innerHTML = str(thexml) document.getElementById("upload").addEventListener("change", create_proxy(upload_handler)) document.addEventListener("drop",create_proxy(drop_handler)) </py-script> </body> </html> ``` I wish there was something cleaner. Calling `event.preventDefault()` failed to work on the drop event from pyscript and no files exist at `event.dataTransfer.files` from pyscript. The base64 encoding was necessary for me as saving to innerHTML removes html entities from xml I was parsing. # Resources - https://www.radiantgrove.com/blog/pyscript/ - https://jeff.glass/post/pyscript-image-upload/ - https://stackoverflow.com/questions/37223723/how-to-create-a-submit-button-using-java-scripts-drag-and-drop-feature - https://github.com/amrrs/pyscript-file-uploader/blob/main/index.html - https://www.angularfix.com/2022/05/how-do-i-use-pyscript-in-my-html-code.html - https://github.com/pyscript/pyscript/blob/img_form/pyscriptjs/examples/img_form.html