Cancel event on input type="file"
I have a perfect solution.
The focus event will be executed before the change event.
So I need to use setTimeout to make the focus method execute later than the change method.
const createUpload = () => {
let lock = false
return new Promise((resolve, reject) => {
// create input file
const el = document.createElement('input')
el.id = +new Date()
el.style.display = 'none'
el.setAttribute('type', 'file')
document.body.appendChild(el)
el.addEventListener('change', () => {
lock = true
const file = el.files[0]
resolve(file)
// remove dom
document.body.removeChild(document.getElementById(el.id))
}, { once: true })
// file blur
window.addEventListener('focus', () => {
setTimeout(() => {
if (!lock && document.getElementById(el.id)) {
reject(new Error('onblur'))
// remove dom
document.body.removeChild(document.getElementById(el.id))
}
}, 300)
}, { once: true })
// open file select box
el.click()
})
}
try {
const file = createUpload()
console.log(file)
} catch(e) {
console.log(e.message) // onblur
}
A bit of research indicates that there is no way to detect when Cancel is selected in the File Selection dialog window. You can use onchange
or onblur
to check if files have been selected or if something has been added to the input value
.
This could look like: https://jsfiddle.net/Twisty/j18td9cs/
HTML
<form>
Select File:
<input type="file" name="test1" id="testFile" />
<button type="reset" id="pseudoCancel">
Cancel
</button>
</form>
JavaScript
var inputElement = document.getElementById("testFile");
var cancelButton = document.getElementById("pseudoCancel");
var numFiles = 0;
inputElement.onclick = function(event) {
var target = event.target || event.srcElement;
console.log(target, "clicked.");
console.log(event);
if (target.value.length == 0) {
console.log("Suspect Cancel was hit, no files selected.");
cancelButton.onclick();
} else {
console.log("File selected: ", target.value);
numFiles = target.files.length;
}
}
inputElement.onchange = function(event) {
var target = event.target || event.srcElement;
console.log(target, "changed.");
console.log(event);
if (target.value.length == 0) {
console.log("Suspect Cancel was hit, no files selected.");
if (numFiles == target.files.length) {
cancelButton.onclick();
}
} else {
console.log("File selected: ", target.value);
numFiles = target.files.length;
}
}
inputElement.onblur = function(event) {
var target = event.target || event.srcElement;
console.log(target, "changed.");
console.log(event);
if (target.value.length == 0) {
console.log("Suspect Cancel was hit, no files selected.");
if (numFiles == target.files.length) {
cancelButton.onclick();
}
} else {
console.log("File selected: ", target.value);
numFiles = target.files.length;
}
}
cancelButton.onclick = function(event) {
console.log("Pseudo Cancel button clicked.");
}
I suggest making your own cancel or reset button that resets the form or clears the value from the input.
In your "inputElement.onclick" you should set a flag (in my case I set window.inputFileTrueClosed = true) so you can detect when the window gets the focus after pressing the button "Cancel" for that type of event. The following detect if the window gets the focus again: it means that "Cancel" button could have been pressed:
var isChrome = !!window.chrome;
window.addEventListener('focus', function (e) {
if(window.inputFileTrueClosed != false){
if(isChrome == true){
setTimeout(
function()
{
if(window.inputFileTrueClosed != false){
//if it is Chrome we have to wait because file.change(function(){... comes after "the window gets the focus"
window.inputFileTrueClosed = false;
}
}, 1000);
}
else
{
// if it is NOT Chrome (ex.Safari) do something when the "cancel" button is pressed.
window.inputFileTrueClosed = false;
}
}
})
Obviously the window gets the focus for many other events BUT with the flag you can select the one you need to detect.
When we select the file following events are called -
Scenario 1 : When the select file is clicked and then cancel is clicked
Focus
event value=""
Click
event value=""
Blur
event value=""
Focus
event value=""
Blur
event value="" (when the user clicks somewhere out)
Scenario 2 : When the file is selected -
Focus
event value=""
Click
event value=""
Blur
event value=""
Focus
event value=""
Change
event value="filevalue"
Blur
event value="filevalue"
Focus
event value="filevalue"
Blur
event value="filevalue" (when the user clicks somewhere out)
We see here, when the Blur event (last event) is called after focus event with no value of file means that the Cancel button is clicked.
My scenario was to change the Submit button text to "Please wait" while the file is loading currentEvent variable is used to hold the current event value either click or focus if the currentEvent = focus and file value is null means Cancel button is clicked.
Javascript
var currentEvent = "focus";
function onFileBrowse() {
var vtbFile = $('#uploadFile')[0].files[0];
if (vtbFile != undefined) {
var extension = vtbFile.name.split('.').pop().toLowerCase();
var valError = "";
if (extension === 'xlsx' || extension === 'xlsb' || extension === 'csv') {
if (vtbFile.size === 0)
valError = "File '" + vtbFile.name + "' is empty";
}
else
valError = "Extension '" + extension + "' is not supported.";
if (valError !== "") {
alert("There was an issue validating the file. " + valError, 20000);
}
}
//hide Indicator
var buttonUpload = document.getElementById('btnUploadTB');
buttonUpload.innerText = "Submit";
};
function fileClick() {
//show Indicator
var buttonUpload = document.getElementById('btnUploadTB');
buttonUpload.innerText = "Please wait..";
document.getElementById('uploadFile').value = null;
currentEvent = "click";
}
function fileFocus() {
currentEvent = "focus";
}
function fileBlur() {
if (!document.getElementById('uploadFile').value && currentEvent == "focus") {
console.log('blur' + 'change to submit');
//hide Indicator
var buttonUpload = document.getElementById('btnUploadTB');
buttonUpload.innerText = "Submit";
}
}
HTML
<input class="k-button k-upload-button" type="file" id="uploadFile" name="uploadFile"
accept=".csv,.xlsx,.xlsb" onChange='onFileBrowse()' onclick="fileClick()" onfocus="fileFocus()" onblur="fileBlur()" />
<button id="btnUploadTB" type="button" class="btn btn-default" onclick="uploadTBFile()" style="width:28%;margin-left: 3px;">Submit</button>