Last active
February 3, 2021 18:52
-
-
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?)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
// 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