File "uploader.js"
Full Path: /home/analogde/www/FormData/upload09/js/uploader.js
File size: 3.03 KB
MIME-type: text/plain
Charset: utf-8
// execute logic on DOM loaded
document.addEventListener("DOMContentLoaded", () => {
// retrieve important DOM elements
const fileUploadElem = document.querySelector("input#file-upload")
const formElem = document.querySelector("form#file-upload-form")
const selectedFilesList = document.querySelector("ul#selected-files-list")
// file input change event - create list item for each selected file
fileUploadElem.addEventListener("change", (event) => {
// careful treating NodeLists like arrays; in old browsers theyre missing many of the properties
Array.from(fileUploadElem.files).forEach((file) => {
let listItem = document.createElement('li')
listItem.innerHTML = file.name + ' - ' + file.type
selectedFilesList.appendChild(listItem)
let progressElem = document.createElement('progress')
progressElem.setAttribute('value',0)
listItem.appendChild(progressElem)
// save reference to create DOM element in file
file.domElement = listItem
})
})
// form submit event
formElem.addEventListener("submit", (event) => {
// prevent normal form submit behavior
event.preventDefault()
// prepare promise execution context
const promiseContext = {
formElem: formElem,
fileUploadElem: fileUploadElem,
selectedFilesList: selectedFilesList
}
// use AsyncSequenceIterator class to upload files sequentially
const iterationCount = fileUploadElem.files.length - 1
new AsyncSequenceIterator(iterationCount, createUploadPromise, promiseContext).whenComplete.then(
// success
() => {
alert('All uploads completed successfully!')
},
// failure
() => {
alert('Error during file uploads.')
}
// disable any further uploads until page refresh
).finally( () => {
formElem.querySelector('input[type=submit').disabled = true
})
})
})
function createUploadPromise(iteration) {
return new Promise((resolve,reject) => {
// create FormData object - add file and form fields manually
const formData = new FormData()
formData.append('fileUpload', this.fileUploadElem.files[iteration])
// dispatch xhr to start file upload - listen to file upload complete event and notify user
let xhr = new XMLHttpRequest()
// set onload (i.e. upload completion) callback
xhr.onload = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
this.selectedFilesList.querySelectorAll('li')[iteration].style.color = 'darkgreen'
resolve()
} else {
this.selectedFilesList.querySelectorAll('li')[iteration].style.color = 'red'
reject()
}
}
// watch for file upload progress
xhr.upload.addEventListener('progress', (e) => {
this.selectedFilesList.querySelectorAll('progress')[iteration].setAttribute("value", (e.loaded / e.total * 100) )
})
// initiate AJAX request
xhr.open("POST", this.formElem.action)
xhr.send(formData)
})
}