Skip to content

Instantly share code, notes, and snippets.

@forresto
Last active February 3, 2021 18:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save forresto/5927a1a24a421f4bcd767e6d7e45e577 to your computer and use it in GitHub Desktop.
Save forresto/5927a1a24a421f4bcd767e6d7e45e577 to your computer and use it in GitHub Desktop.
pickFile: vanilla dom typescript function (promise / async friendly) to pick a file (why isn't this a standard dom function?)
/*
// How to use
export const triggerSVGImportFilePicker = async () => {
const files = await pickFile({ accept: ".svg" });
if (files && files.length) {
handleFiles(files);
}
};
*/
interface PickFileOptions {
accept: string;
}
export const pickFile = (options: PickFileOptions): Promise<FileList | void> => {
return new Promise((resolve) => {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", options.accept);
// Might not need to actually be in DOM?
input.style.position = "fixed";
input.style.top = "-1080px";
document.body.appendChild(input);
input.addEventListener("change", (event: Event) => {
const files = (event.target as HTMLInputElement).files;
if (files) {
resolve(files);
} else {
resolve();
}
cleanUp();
});
input.click();
// Because <input type=file> does not fire a cancel event, we have to also
// clean up with any future clicks
const cleanUp = () => {
input.parentElement?.removeChild(input);
window.removeEventListener("click", resolveAndCleanUp);
};
const resolveAndCleanUp = () => {
resolve();
cleanUp();
};
// Need timeout, otherwise the click event that calls pickFile also cleans it up
setTimeout(() => {
window.addEventListener("click", resolveAndCleanUp);
});
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment