如何检测文件输入何时单击取消?
如何检测用户何时使用 html 文件输入取消文件输入?
onChange 让我检测他们何时选择文件,但我也想知道他们何时取消(关闭文件选择对话框而不选择任何内容)。
How can I detect when the user cancels a file input using an html file input?
onChange lets me detect when they choose a file, but I would also like to know when they cancel (close the file choose dialog without selecting anything).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
如果 Shiboe 的解决方案适用于移动 webkit,那么它会是一个很好的解决方案,但事实并非如此。我能想到的是在文件输入窗口打开时向某个 dom 对象添加一个 mousemove 事件监听器,如下所示:
当文件对话框打开时以及关闭时,mousemove 事件会被页面阻止检查文件输入中是否有任何文件。就我而言,我想要一个活动指示器阻止事情直到文件上传,所以我只想在取消时删除我的指示器。
然而,这并不能解决移动设备的问题,因为没有鼠标可以移动。我的解决方案并不完美,但我认为它已经足够好了。
现在我们正在监听屏幕上的触摸来执行相同的文件检查。我非常有信心,在取消并关闭此活动指示器后,用户的手指将很快放在屏幕上。
人们还可以在文件输入更改事件上添加活动指示器,但在移动设备上,选择图像和更改事件触发之间通常会有几秒钟的延迟,因此将活动指示器显示在文件输入更改事件上会带来更好的用户体验。该过程的开始。
Shiboe's solution would be a good one if it worked on mobile webkit, but it doesn't. What I can come up with is to add a mousemove event listener to some dom object at the time that the file input window is opened, like so:
The mousemove event is blocked from the page while the file dialog is open, and when its closed one checks to see if there are any files in the file input. In my case I want an activity indicator blocking things till the file is uploaded, so I only want to remove my indicator on cancel.
However this doesn't solve for mobile, since there is no mouse to move. My solution there is less than perfect, but I think its good enough.
Now we're listening for a touch on the screen to do the same files check. I'm pretty confident that the user's finger will be put on the screen pretty quickly after cancel and dismiss this activity indicator.
One could also just add the activity indicator on the file input change event, but on mobile there is often a few seconds lag between selecting the image and the change event firing, so its just much better UX for the activity indicator to be displayed at the start of the process.
我发现这个属性,它是最简单的。
这里,
selectedFile
是一个input type=file
。I found this atribute, its most simple yet.
Here,
selectedFile
is aninput type=file
.我知道这是一个非常古老的问题,但为了防止它对某人有帮助,我发现在使用 onmousemove 事件来检测取消时,有必要在短时间内测试两个或多个此类事件。
这是因为每次将光标移出选择文件对话框窗口以及每次移出主窗口并返回时,浏览器 (Chrome 65) 都会生成单个 onmousemove 事件。
鼠标移动事件的简单计数器加上将计数器重置为零的短持续时间超时,效果很好。
I know this is a very old question but just in case it helps someone, I found when using the onmousemove event to detect the cancel, that it was necessary to test for two or more such events in a short space of time.
This was because single onmousemove events are generated by the browser (Chrome 65) each time the cursor is moved out of the select file dialog window and each time it is moved out of the main window and back in.
A simple counter of mouse movement events coupled with a short duration timeout to reset the counter back to zero worked a treat.
结合 Shiboe 和 alx 的解决方案,我得到了最可靠的代码:
通常, mousemove 事件可以解决问题,但如果用户单击了鼠标,则:
因此我们不会收到 mousemove 事件没有取消回调。此外,如果用户取消第二个对话框并移动鼠标,我们将收到 2 个取消回调。
幸运的是,在这两种情况下,特殊的 jQuery focusIn 事件都会冒泡到文档中,帮助我们避免这种情况。唯一的限制是如果其中之一阻止 focusIn 事件。
Combining Shiboe's and alx's solutions, i've got the most reliable code:
Generally, mousemove event does the trick, but in case user made a click and than:
... we won't get mousemove event hence no cancel callback. Moreover, if user cancels second dialog and makes a mouse move, we'll get 2 cancel callbacks.
Fortunately, special jQuery focusIn event bubbles up to the document in both cases, helping us to avoid such situations. The only limitation is if one blocks focusIn event either.
我发现我的回应已经相当过时了,但仍然如此。
我面临着同样的问题。这是我的解决方案。
被截断的最有用的代码是 KGA 的代码。但它并不完全有效,而且有点复杂。但我把它简化了。
另外,主要的麻烦在于,“改变”事件在焦点之后不会立即发生,所以我们必须等待一段时间。
“#appendfile” - 用户单击该按钮来追加新文件。
Href 获取焦点事件。
I see that my response would be quite outdated, but never the less.
I faced with the same problem. So here's my solution.
The most useful code snipped was KGA's one. But it isn't totally working and is a bit complicated. But I simplified it.
Also, the main trouble maker was that fact, that 'change' event doesn't come instantly after focus, so we have to wait for some time.
"#appendfile" - which user clicks on to append a new file.
Hrefs get focus events.
您只能在有限的情况下检测到这一点。具体来说,在 Chrome 中,如果之前选择了文件,然后单击文件对话框并单击取消,Chrome 会清除该文件并触发 onChange 事件。
https://code.google.com/p/chromium/issues/detail ?id=2508
在这种情况下,您可以通过处理 onChange 事件并检查 files 属性来检测这一点。
You can detect this only in limited circumstances. Specifically, in chrome if a file was selected earlier and then the file dialog is clicked and cancel clicked, Chrome clears the file and fires the onChange event.
https://code.google.com/p/chromium/issues/detail?id=2508
In this scenario, you can detect this by handling the onChange event and checking the files property.
这充其量只是hacky,但这是我的解决方案的一个工作示例,用于检测是否用户已上传文件,并且仅允许他们在上传文件后继续。
基本上隐藏
Continue
、Save
、Proceed
或任何按钮。然后在 JavaScript 中获取文件名。如果文件名没有值,则不显示继续
按钮。如果它确实有值,则显示按钮。如果他们首先上传文件,然后尝试上传不同的文件并单击“取消”,这也适用。这是代码。
HTML:
JavaScript:
CSS:
对于 CSS,这很大程度上是为了让每个人都可以访问网站和按钮。将按钮设计成您喜欢的任何样式。
This is hacky at best, but here is a working example of my solution to detect whether or not a user has uploaded a file, and only allowing them to proceed if they have uploaded a file.
Basically hide the
Continue
,Save
,Proceed
or whatever your button is. Then in the JavaScript you grab the file name. If the file name does not have a value, then do not show theContinue
button. If it does have a value, then show the button. This also works if they at first upload a file and then they try to upload a different file and click cancel.Here is the code.
HTML:
JavaScript:
CSS:
For the CSS a lot of this is to make the website and button accessible for everyone. Style your button to whatever you like.
以下内容似乎对我有用(在桌面、Windows 上):
这确实使用 angularjs $q 但如果需要,您应该能够将其替换为任何其他承诺框架。
在 IE11、Edge、Chrome、Firefox 上进行了测试,但它似乎不适用于 Android 平板电脑上的 Chrome,因为它不会触发 Focus 事件。
The following seems to work for me (on desktop, windows):
This does use angularjs $q but you should be able to replace it with any other promise framework if needed.
Tested on IE11, Edge, Chrome, Firefox, but it does not seem to work on Chrome on a Android Tablet as it does not fire the Focus event.
令人沮丧的是,
file
类型字段无法响应很多事件(模糊会很可爱)。我看到很多人建议以变革为导向的解决方案,但遭到了否决。change
确实有效,但它有一个重大缺陷(与我们希望发生的情况相比)。当您新加载包含文件字段的页面时,打开该框并按取消。令人沮丧的是,什么都没有改变。
我选择做的是在门控状态下加载。
文件字段
更改时,会显示上传按钮。成功上传后,将显示section#after-image
。change
事件,我可以(并且确实)重新隐藏我的上传按钮,直到选择正确的文件。我很幸运,这种门控状态已经是我表单的设计。您不需要使用相同的样式,只需将上传按钮最初隐藏起来,并在更改后将隐藏字段或 JavaScript 变量设置为您可以在提交时监视的内容。
我尝试在与字段交互之前更改 files[0] 的值。这对 onchange 没有做任何事情。
所以,是的,
change
有效,至少和我们想要的一样好。出于显而易见的原因,文件字段是安全的,但令善意的开发人员感到沮丧。这不符合我的目的,但您也许可以,
onclick
,加载警告提示(不是alert()
,因为这会停止页面处理),并且如果触发更改且 files[0] 为 null,则隐藏它。如果未触发更改,则 div 保持其状态。The
file
-type field, frustratingly, doesn't respond to a lot of events (blur would be lovely). I see a lot of people suggestingchange
-oriented solutions and them getting downvoted.change
does work, but it has a major flaw (vs what we want to happen).When you freshly load a page containing a file field, open the box and press cancel. Nothing, frustratingly, changes.
What I chose to do is load in a gated-state.
section#after-image
in my case is hidden from view. When myfile field
changes, an upload button is shown. Upon successful upload,section#after-image
is shown.change
event is triggered by this cancel, and there I can (and do) re-hide my upload button until a proper file is selected.I was fortunate that this gated-state was already the design of my form. You do not need to use the same style, merely having the upload button initially hidden and upon change, setting a hidden field or javascript variable to something you can monitor on submit.
I tried changing the value of files[0] before the field was interacted with. This didn't do anything regarding onchange.
So yes,
change
works, at least as good as we're going to get. The filefield is secured, for obvious reasons, but to the frustration of well-intentioned developers.It's not fitting to my purpose, but you might be able to,
onclick
, load a warning prompt (not analert()
, because that stalls page-processing), and hide it if change is triggered and files[0] is null. If change is not triggered, the div remains in its state.使用隐藏输入选择文件的解决方案
注意:此代码不会检测取消,它提供了一种方法来避免在人们尝试检测它的常见情况下检测它。
我在寻找使用隐藏输入的文件上传解决方案时来到这里,我相信这是寻找一种检测文件输入取消的方法的最常见原因(打开文件对话框 -> 如果选择了文件然后运行一些代码,否则什么都不做),这是我的解决方案:
使用示例:
请注意,如果没有选择文件,那么第一行将仅在再次调用
selectFile()
时返回(或者如果您调用fileSelectorResolve())。
另一个例子:
Solution for file selection with hidden input
Note: this code doesn't detect cancellation, it offers a way to circumvent the need to detect it in a common case in which people try to detect it.
I got here while looking for a solution for file uploads using a hidden input, I believe that this is the most common reason to look for a way to detect cancellation of file input (open file dialog -> if a file was selected then run some code, otherwise do nothing), here's my solution:
Usage example:
Note that if no file was selected then the first line will return only once
selectFile()
is called again (or if you calledfileSelectorResolve()
from elsewhere).Another example:
我发现这个问题 https://github.com/whatwg/html/pull/6735 由 https://github.com/WebKit/WebKit/pull/4986 合并到 WebKit 中
HTMLDialogElement 还实现了取消事件:
https://developer.mozilla.org/en-US/docs/ Web/API/HTMLDialogElement
下面是一个带有更改和取消事件监听的示例代码:
https://stackblitz.com/edit/js-lzmne4
I found this issue https://github.com/whatwg/html/pull/6735 that is merged in WebKit by https://github.com/WebKit/WebKit/pull/4986
The HTMLDialogElement also implements the cancel event:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement
Here is a sample code with change and cancel event listening:
https://stackblitz.com/edit/js-lzmne4
有一种黑客方法可以做到这一点(添加回调或解决一些延迟/承诺实现,而不是
alert()
调用):它是如何工作的:当文件选择对话框打开时,文档不接收鼠标指针事件。有 1000 毫秒的延迟让对话框实际出现并阻止浏览器窗口。在 Chrome 和 Firefox(仅限 Windows)中检查。
但这当然不是检测取消对话的可靠方法。不过,可能会为您改进一些 UI 行为。
There is a hackish way to do this (add callbacks or resolve some deferred/promise implementation instead of
alert()
calls):How it works: while file selection dialog is open, document does not receive mouse pointer events. There is 1000ms delay to allow the dialog to actually appear and block browser window. Checked in Chrome and Firefox (Windows only).
But this is not a reliable way to detect cancelled dialog, of course. Though, might improve some UI behavior for you.
这是我的解决方案,使用文件输入焦点(不使用任何计时器)
Here is my solution, using the file input focus (not using any timers)
嗯,这并不能完全回答你的问题。我的假设是,您有一个场景,当您添加文件输入并调用文件选择时,如果用户点击取消,您只需删除输入。
如果是这样的话:为什么要添加空文件输入呢?
动态创建一个,但仅在填充时将其添加到 DOM。就像这样:
所以在这里我创建了 即时绑定到它的更改事件,然后立即调用单击。仅当用户选择文件并单击“确定”时才会触发“更改”,否则输入将不会添加到 DOM,因此不会提交。
此处的工作示例: https://jsfiddle.net/69g0Lxno/3/
Well, this doesn't exactly answers your question. My assumption is that, you have a scenario, when you add a file input, and invoke file selection, and if user hits cancel, you just remove the input.
If this is the case, then: Why adding empty file input?
Create the one on the fly, but add it to DOM only when it is filled in. Like so:
So here I create <input type="file" /> on the fly, bind to it's change event and then immediately invoke click. On change will fire only when user selects a file and hits Ok, otherwise input will not be added to DOM, therefore will not be submitted.
Working example here: https://jsfiddle.net/69g0Lxno/3/
//使用悬停而不是模糊
//Use hover instead of blur
使用setTimeout来获取输入的特定值。
Using setTimeout to get the certain value of the input.
如果您已经需要 JQuery,则此解决方案可能会完成工作(这与我在本例中实际需要的代码完全相同,尽管使用 Promise 只是强制代码等待直到文件选择已解决):
});
If you already require JQuery, this solution might do the work (this is the exact same code I actually needed in my case, although using a Promise is just to force the code to wait until file selection has been resolved):
});
该线程中提出了几种解决方案,而难以检测用户何时单击文件选择框上的“取消”按钮是影响很多人的问题。
事实是,没有 100% 可靠的方法来检测用户是否单击了文件选择框上的“取消”按钮。但是有一些方法可以可靠地检测用户是否已将文件添加到输入文件。所以这就是本次回答的基本策略!
我决定添加这个答案,因为显然其他答案不适用于大多数浏览器或保证在移动设备上。
简而言之,代码基于 3 点:
(目前我们不将其添加到“HTML”中);
HTML 通过特定的事件,这意味着
文件的“编辑”/“修改”是通过删除旧的来完成的
输入文件并创建一个新文件。
为了更好地理解,请查看下面的代码和注释。
谢谢! =D
There are several proposed solutions in this thread and this difficulty to detecting when the user clicks the "Cancel" button on the file selection box is a problem that affects many people.
The fact is that there is no 100% reliable way to detect if the user has clicked the "Cancel" button on the file selection box. But there are ways to reliably detect if the user has added a file to the input file. So this is the basic strategy of this answer!
I decided to add this answer because apparently the other answers don't work on most browsers or guaranteed on mobile devices.
Briefly the code is based on 3 points:
(we don't add it to the "HTML" at this moment);
HTML by a specific event, which means that the
"editing"/"modification" of the file is done by removing the old
input file and creating a new one.
For a better understanding look at the code below and the notes as well.
Thanks! =D
虽然不是一个直接的解决方案,而且也不好,因为它只能(据我测试)与 onfocus 一起工作(需要相当有限的事件阻止),您可以通过以下方式实现它:
这个的好处是,您可以与文件事件一起及时附加/分离它,并且它似乎也可以很好地处理隐藏输入(如果您对蹩脚的默认输入类型=“文件”使用视觉解决方法,那么这是一个明确的好处)。之后,您只需要弄清楚输入值是否发生变化。
示例:
查看实际操作: http://jsfiddle.net/Shiboe/yuK3r/6/
遗憾的是,它似乎只适用于 webkit 浏览器。也许其他人可以找出 firefox/IE 解决方案
While not a direct solution, and also bad in that it only (as far as I've tested) works with onfocus (requiring a pretty limiting event blocking) you can achieve it with the following:
What's nice about this, is that you can attach/detach it in time with the file event, and it also seems to work fine with hidden inputs (a definite perk if you're using a visual workaround for the crappy default input type='file'). After that, you just need to figure out if the input value changed.
An example:
See it in action: http://jsfiddle.net/Shiboe/yuK3r/6/
Sadly, it only seems to work on webkit browsers. Maybe someone else can figure out the firefox/IE solution
因此,自从我提出了一个新颖的解决方案以来,我将彻底解决这个问题。我有一个渐进式网络应用程序,允许用户捕获照片和视频并上传它们。我们尽可能使用 WebRTC,但对于支持较少的设备,我们会使用 HTML5 文件选择器*咳嗽 Safari 咳嗽*。 如果您专门开发使用本机相机直接捕获照片/视频的 Android/iOS 移动网络应用程序,那么这是我遇到的最佳解决方案。
这个问题的关键是当页面加载时,
file
为null
,但是当用户打开对话框并按“取消”时,file
仍为null
null
,因此它没有“更改”,因此不会触发“更改”事件。对于台式机来说,这还不算太糟糕,因为大多数桌面 UI 并不依赖于知道何时调用取消,但调出相机来捕获照片/视频的移动 UI 非常依赖于知道何时按下取消键。我最初使用 document.body.onfocus 事件来检测用户何时从文件选择器返回,这适用于大多数设备,但 iOS 11.3 破坏了它,因为该事件未触发。
概念
我对此的解决方案是“颤抖”,测量 CPU 时序以确定页面当前是在前台还是后台。在移动设备上,处理时间分配给当前位于前台的应用程序。当摄像头可见时,它会窃取 CPU 时间并降低浏览器的优先级。我们需要做的就是测量我们的页面有多少处理时间,当相机启动时,我们的可用时间将急剧下降。当相机关闭(取消或其他方式)时,我们的可用时间会增加。
实现
我们可以通过使用 setTimeout() 在 X 毫秒内调用回调来测量 CPU 计时,然后测量实际调用它需要多长时间。浏览器永远不会在 X 毫秒后准确调用它,但如果它合理接近,那么我们一定位于前台。如果浏览器距离很远(比请求的速度慢 10 倍以上),那么我们一定处于后台。其基本实现如下:
我在最新版本的 iOS 和 Android 上对此进行了测试,通过设置
元素上的属性来调出本机相机。
这实际上比我预期的要好得多。它通过请求在 25 毫秒内调用计时器来运行 10 次试验。然后,它会测量调用实际花费的时间,如果 10 次尝试的平均值小于 50 毫秒,我们就假设我们一定位于前台,并且相机消失了。如果大于50毫秒,那么我们一定还在后台,应该继续等待。
我使用了
setTimeout()
而不是setInterval()
,因为后者可以对多个调用进行排队,这些调用会立即执行。这可能会大大增加数据中的噪声,因此我坚持使用 setTimeout(),尽管这样做有点复杂。这些特定的数字对我来说效果很好,尽管我至少见过一次过早检测到相机关闭的情况。我相信这是因为相机打开速度可能很慢,并且设备在实际进入后台之前可能会运行 10 次试验。添加更多试验或在启动此功能之前等待大约 25-50 毫秒可能是解决此问题的方法。
桌面
不幸的是,这实际上不适用于桌面浏览器。理论上,同样的技巧是可能的,因为它们确实优先考虑当前页面而不是背景页面。然而,许多桌面有足够的资源来保持页面全速运行,即使在后台运行,因此这种策略在实践中并不真正有效。
替代解决方案
没有多少人提到我确实探索过的一种替代解决方案是模拟
FileList
。我们从中的
null
开始,然后如果用户打开相机并取消,他们会返回到null
,这不是更改,不会触发任何事件。一种解决方案是在页面开始时将虚拟文件分配给,因此设置为
null
将是一个会触发适当事件的更改。不幸的是,没有正式的方法来创建
FileList
,并且元素特别需要
FileList
并且不会接受除null
之外的任何其他值。当然,FileList
对象不能直接构造,这是为了解决一些显然不再相关的旧安全问题。获取元素之外的唯一方法是利用一种 hack,复制粘贴数据来伪造剪贴板事件,其中可以包含
FileList 对象(您基本上是在伪造一个在您的网站上拖放文件的事件)。这在 Firefox 中是可行的,但不适用于 iOS Safari,因此它对于我的特定用例来说不可行。
浏览器,拜托……
不用说,这显然是荒谬的。事实上,网页对于关键 UI 元素已更改的通知为零,这简直是可笑的。这确实是规范中的一个错误,因为它从来没有打算用于全屏媒体捕获 UI,并且从技术上讲,不触发“更改”事件是符合规范的。
但是,浏览器厂商能否认清这个现实?这可以通过一个新的“完成”事件来解决,即使没有发生任何更改也会触发该事件,或者您也可以只是触发“更改”。是的,这违反了规范,但对我来说,在 JavaScript 端删除更改事件是微不足道的,但从根本上不可能发明我自己的“完成”事件。即使我的解决方案实际上只是启发式的,如果不能保证浏览器的状态。
就目前情况而言,这个 API 基本上无法用于移动设备,我认为相对简单的浏览器更改可以使 Web 开发人员变得更加容易 * 摆脱肥皂盒 *。
So I'll throw my hat into this question since I came up with a novel solution. I have a Progressive Web App which allows users to capture photos and videos and upload them. We use WebRTC when possible, but fall back to HTML5 file pickers for devices with less support *cough Safari cough*. If you're working specifically on an Android/iOS mobile web application which uses the native camera to capture photos/videos directly, then this is the best solution I have come across.
The crux of this problem is that when the page loads, the
file
isnull
, but then when the user opens the dialog and presses "Cancel", thefile
is stillnull
, hence it did not "change", so no "change" event is triggered. For desktops, this isn't too bad because most desktop UI's aren't dependent on knowing when a cancel is invoked, but mobile UI's which bring up the camera to capture a photo/video are very dependent on knowing when a cancel is pressed.I originally used the
document.body.onfocus
event to detect when the user returned from the file picker, and this worked for most devices, but iOS 11.3 broke it as that event is not triggered.Concept
My solution to this is *shudder* to measure CPU timing to determine if the page is currently in the foreground or the background. On mobile devices, processing time is given to the app currently in the foreground. When a camera is visible it will steal CPU time and deprioritize the browser. All we need to do is measure how much processing time our page is given, when camera launches our available time will drop drastically. When the camera is dismissed (either cancelled or otherwise), our available time spike back up.
Implementation
We can measure CPU timing by using
setTimeout()
to invoke a callback in X milliseconds, and then measure how long it took to actually invoke it. The browser will never invoke it exactly after X milliseconds, but if it is reasonable close then we must be in the foreground. If the browser is very far away (over 10x slower than requested) then we must be in the background. A basic implementation of this is like so:I tested this on recent version of iOS and Android, bringing up the native camera by setting the attributes on the
<input />
element.This works out actually a lot better than I expected. It runs 10 trials by requesting a timer to be invoked in 25 milliseconds. It then measures how long it actually took to invoke, and if the average of 10 trials is less than 50 milliseconds, we assume that we must be in the foreground and the camera is gone. If it is greater than 50 milliseconds, then we must still be in the background and should continue to wait.
Some additional details
I used
setTimeout()
rather thansetInterval()
because the latter can queue multiple invocations which execute immediately after each other. This could drastically increase the noise in our data, so I stuck withsetTimeout()
even though it is a little more complicated to do so.These particular numbers worked well for me, though I have see at least once instance where the camera dismiss was detected prematurely. I believe this is because the camera may be slow to open, and the device may run 10 trials before it actually becomes backgrounded. Adding more trials or waiting some 25-50 milliseconds before starting this function may be a workaround for that.
Desktop
Unfortuantely, this doesn't really work for desktop browsers. In theory the same trick is possible as they do prioritize the current page over backgrounded pages. However many desktops have enough resources to keep the page running at full speed even when backgrounded, so this strategy doesn't really work in practice.
Alternative solutions
One alternative solution not many people mention that I did explore was mocking a
FileList
. We start withnull
in the<input />
and then if the user opens the camera and cancels they come back tonull
, which is not a change and no event will trigger. One solution would be to assign a dummy file to the<input />
at page start, therefore setting tonull
would be a change which would trigger the appropriate event.Unfortunately, there's no way official way to create a
FileList
, and the<input />
element requires aFileList
in particular and will not accept any other value besidesnull
. Naturally,FileList
objects cannot be directly constructed, do to some old security issue which isn't even relevant anymore apparently. The only way to get ahold of one outside of an<input />
element is to utilize a hack which copy-pastes data to fake a clipboard event which can contain aFileList
object (you're basically faking a drag-and-drop-a-file-on-your-website event). This is possible in Firefox, but not for iOS Safari, so it was not viable for my particular use case.Browsers, please...
Needless to say this is patently ridiculous. The fact that web pages are given zero notification that a critical UI element has changed is simply laughable. This is really a bug in the spec, as it was never intended for a full-screen media capture UI, and not triggering the "change" event is technically to spec.
However, can browser vendors please recognize the reality of this? This could be solved with either a new "done" event which is triggered even when no change occurs, or you could just trigger "change" anyways. Yeah, that would be against spec, but it is trivial for me to dedup a change event on the JavaScript side, yet fundamentally impossible to invent my own "done" event. Even my solution is really just heuristics, if offer no guarantees on the state of the browser.
As it stands, this API is fundamentally unusable for mobile devices, and I think a relatively simple browser change could make this infinitely easier for web developers *steps off soap box*.
你不能。
文件对话框的结果不会暴露给浏览器。
You can't.
The result of the file dialog is not exposed to the browser.
新的文件系统访问 API 将使我们的生活再次变得轻松: )
浏览器支持非常有限(2021 年 1 月)。该示例代码在 Chrome 桌面 86 中运行良好。
The new File System Access API will make our life easy again :)
Browser support is very limited (Jan, 2021). The example code works well in Chrome Desktop 86.
当您选择文件并单击打开/取消时,
input
元素应该失去焦点,即模糊
。假设input
的初始value
为空,blur
处理程序中的任何非空值都表示 OK,空值表示取消。更新:隐藏
输入
时,不会触发模糊
。因此,不能在基于 IFRAME 的上传中使用此技巧,除非您想临时显示输入
。When you select a file and click open/cancel, the
input
element should lose focus akablur
. Assuming the initialvalue
of theinput
is empty, any non empty value in yourblur
handler would indicate an OK, and an empty value would mean a Cancel.UPDATE: The
blur
is not triggered when theinput
is hidden. So can't use this trick with IFRAME-based uploads, unless you want to temporarily display theinput
.这些解决方案中的大多数对我来说不起作用。
问题是你永远不知道哪个事件会首先被触发,
是
点击
还是更改
?您不能假设任何顺序,因为它可能取决于浏览器的实现。至少在 Opera 和 Chrome 中(2015 年末),
click
会在用文件“填充”输入之前触发,因此您永远不会知道files.length != 0
的长度直到您延迟点击
在更改
后触发。这是代码:
Most of these solutions don't work for me.
The problem is that you never know which event will be triggered fist,
is it
click
or is itchange
? You can't assume any order, because it probably depends on the browser's implementation.At least in Opera and Chrome (late 2015)
click
is triggered just before 'filling' input with files, so you will never know the length offiles.length != 0
until you delayclick
to be triggered afterchange
.Here is code:
也只需监听点击事件即可。
继 Shiboe 的示例之后,这里有一个 jQuery 示例:
您可以在此处查看它的实际效果: http://jsfiddle.net/T3Vwz
Just listen to the click event as well.
Following from Shiboe's example, here's a jQuery example:
You can see it in action here: http://jsfiddle.net/T3Vwz
现代浏览器为输入文件添加了取消事件
请参阅浏览器支持 caniuse
Modern browsers have added a cancel event for input file
See browser support at caniuse
如果您选择与之前相同的文件并单击“取消”,则可以捕获取消:在这种情况下。
你可以这样做:
You can catch the cancel if you choose the same file as previously and you click cancel: in this case.
You can do it like this:
最简单的方法是检查临时内存中是否有文件。如果您想在每次用户单击文件输入时获取更改事件,您可以触发它。
The easiest way is to check if there are any files in temporary memory. If you want to get the change event every time user clicks the file input you can trigger it.
就我而言,我必须在用户选择图像时隐藏提交按钮。
这就是我的想法:
#image-field
是我的文件选择器。当有人点击它时,我禁用表单提交按钮。关键是,当文件对话框关闭时 - 无论他们选择文件还是取消 -#image-field
重新获得焦点,所以我监听该事件。更新
我发现,这在 safari 和 poltergeist/phantomjs 中不起作用。如果您想实施它,请考虑此信息。
In my case i had to hide submit button while users were selecting images.
This is what i come up:
#image-field
is my file selector. When somenone clicks on it, i disable the form submit button. The point is, when the file dialog closed - doesn't matter they select a file or cancel -#image-field
got the focus back, so i listen on that event.UPDATE
I found that, this does not work in safari and poltergeist/phantomjs. Take this info into account if you would like to implement it.