I am facing an issue in detecting a file input window close event in js
what I am trying:
<input type="file" />
const input = document.querySelector("input");
input.addEventListener("change", handleFileUpload);
async function handleFileUpload(event) {
if (event.userCancel) {
// <--- where can I get this?? or something similar in function
// do something
}
const files = event.target.files;
await doUpload(files); // upload the files
}
Any advice on how to fix this?
I've tested the following solution in latest Chrome, Firefox and Safari on my Mac (May, 2023) and it seems to work fine (an in-depth explanation follows below the code):
const sleep = ms => new Promise(res => setTimeout(res, ms));
const input = document.querySelector("input");
input.addEventListener('click', () => handleFileUpload());
async function handleFileUpload() {
input.value = '';
let closed = false;
let ua = navigator.userAgent.toLowerCase().toLowerCase();
let firefoxOrSafari = ua.includes('firefox') || ua.includes('safari');
let eventType = firefoxOrSafari ? 'mouseover' : 'focus';
let listener = window.addEventListener(eventType, () => closed = true);
while (!closed) {
await sleep(100);
!firefoxOrSafari && input.focus();
}
window.removeEventListener(eventType, listener);
await sleep(1000);
const files = input.files;
if (!files.length) {
alert('No file upload today then?')
}
else {
alert('Uploading!\n\n'
+ [...files].map(({ name }) => name).join('\n'));
// await doUpload(files); // upload the files
input.value = '';
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sticky Color</title>
<link rel="stylesheet" href="sticky-color.css">
</head>
<body>
<input type="file" multiple>
</body>
</html>
Note: This solution is sensitive to the user moving they mouse outside the viewport during the time the file dialog is open. This is rather unlikely though. And the 'close' triggers once they move the mouse back inside the viewport. (For us developers it is more likely to move outside the viewport since we might have the console/dev tools open. And when running the code snippet here it runs in a small iframe, so it is rather likely that you move outside that iframe.)
Update: Unfortunately the mouseover event sometimes triggers on Chromium/Blink even when the dialog is open, so I opted for keeping the original solution in Firefox and Safari and going with another one for other browsers (~ probably Chrome-based): Listen to focus of the input field, and while we wait try to focus the input field - in Chrome this doesn't work as long as the dialog is open... I don't like having to version things per browser, but can't find away around it. The code has been updated.
And DO note: Not tested on or adopted for mobile devices.