I want a function which prompts the user to select an image. It should then wait for an image to be selected and then return that image. I want to achieve this without creating a new input element and attaching a new eventlistener every time (atleast not without removing the old ones first) because I expect this button to be used A LOT!
What I have right now is successfully prompting the user can getting the image. But I am not returning it so I can use it however I want after the prompt_for_image() function call. Please help me D:
I added a console log button for testing purposes so you can see the image is being selected propperly.
const images = [];
const file_input = document.createElement('input');
file_input.type = 'file';
file_input.accept = 'image/*';
file_input.addEventListener('change', () => {
const reader = new FileReader();
reader.onload = () => images.push(reader.result);
reader.readAsDataURL(file_input.files[0]);
});
function prompt_for_image() {
file_input.value = null;
file_input.click();
}
document.getElementById('btn_add_new_image').addEventListener('click', async () => {
await prompt_for_image();
});
document.getElementById('btn_log_images').addEventListener('click', () => { console.log(images) });
<button type='button' id='btn_add_new_image'>ADD NEW IMAGE</button>
<button type='button' id='btn_log_images'>console log image array</button>
CodePudding user response:
You'll need to properly promisify FileReader
, then promisify the addEventListener
. This is easiest done by using the once
parameter:
function readFileAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function waitForNextEvent(element, type) {
return new Promise(resolve => {
element.addEventListener(type, resolve, {once: true});
});
}
Now you can do
const images = [];
const fileInput = Object.assign(document.createElement('input'), {
type: 'file',
accept: 'image/*',
});
async function promptForImage() {
const promise = waitForNextEvent(fileInput, 'change');
fileInput.value = null;
fileInput.click();
await promise;
return fileInput.files[0];
}
document.getElementById('btn_add_new_image').addEventListener('click', async () => {
images.push(await readFileAsDataURL(await promptForImage()));
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
});
document.getElementById('btn_log_images').addEventListener('click', () => {
console.log(images);
});
function readFileAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function waitForNextEvent(element, type) {
return new Promise(resolve => {
element.addEventListener(type, resolve, {once: true});
});
}
<button type='button' id='btn_add_new_image'>ADD NEW IMAGE</button>
<button type='button' id='btn_log_images'>console log image array</button>