在输入类型="文件"上取消事件

GWR*_*GWR 18 javascript jquery file-upload

我正在使用标准文件输入进行上传,我正在寻找一种方法,当用户点击/点击输入"取消"按钮(或从"退出"选择文件对话框)时,将功能附加到事件.

我无法找到任何适用于所有浏览器和平台的事件.

我已经阅读了这个问题的答案:在输入类型=文件上捕获取消事件但它们不起作用,因为在取消选择文件对话框时大多数浏览器都不会触发更改事件.

我正在寻找一个纯粹的js解决方案,但也可以使用jquery解决方案.

有人成功解决了这个问题吗

Twi*_*sty 12

一些研究表明,在"文件选择"对话框窗口中无法检测何时选择"取消".您可以使用onchangeonblur检查是否已选择文件或是否已将某些内容添加到输入中value.

这看起来像:https://jsfiddle.net/Twisty/j18td9cs/

HTML

<form>
  Select File:
  <input type="file" name="test1" id="testFile" />
  <button type="reset" id="pseudoCancel">
    Cancel
  </button>
</form>
Run Code Online (Sandbox Code Playgroud)

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.");
}
Run Code Online (Sandbox Code Playgroud)

我建议您自己取消或重置按钮,重置表单或清除输入中的值.


Kai*_*ido 12

现在cancel在这种情况下会触发一个事件,大约一年以来所有 3 个主要浏览器引擎都支持该事件(Chrome 和 Firefox 为 2 个)。

document.querySelector("input").addEventListener("cancel", (evt) => {
  console.log("You closed the file picker dialog without selecting a file.");
});
Run Code Online (Sandbox Code Playgroud)
<input type="file">
Run Code Online (Sandbox Code Playgroud)

不幸的是,我们无法使用oncancel全局处理程序来检测此事件,因为这可能指向<dialog>元素上触发的同音事件,从而导致误报。因此,据我所知,没有简单的检测途径。

  • 它有效且优雅,仅供参考,这是 2023 年才添加的,希望这个答案能够到达顶部。 (2认同)

hoy*_*han 6

我有一个完美的解决方案。

焦点事件将在更改事件之前执行。

所以我需要使用 setTimeout 来让 focus 方法晚于 change 方法执行。

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
}
Run Code Online (Sandbox Code Playgroud)