javascript 文件输入更改事件仅触发一次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7179627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Files input change event fires only once
提问by Cokegod
I've made a small script using some of the HTML5 files features, which allows you to select one or more files, and each time it will write the name of the file(s). Everything works as it should, only the event to detect the value change of the files input fire only once, so how can I make it fire every change and not only on the first change?
我已经使用一些 HTML5 文件功能制作了一个小脚本,它允许您选择一个或多个文件,并且每次都会写入文件的名称。一切正常,只有检测文件输入值更改的事件只触发一次,那么我怎样才能让它在每次更改时触发,而不仅仅是在第一次更改时触发?
By the way, here is what I made: http://tamir.netspot.co.il/html5/files/
顺便说一句,这是我做的:http: //tamir.netspot.co.il/html5/files/
采纳答案by Flambino
It appears that the change
event listener is being removed because you're using innerHTML
to update the same element (wrapper
) that the input itself is inside. So the contents of the wrapper
element – including the file input – is being re-rendered, and along the way, the event listener is removed (or, rather, it's connected to an element that's no longer there).
change
事件侦听器似乎正在被删除,因为您正在使用innerHTML
更新wrapper
输入本身所在的相同元素 ( )。所以wrapper
元素的内容——包括文件输入——正在被重新渲染,并且在此过程中,事件侦听器被删除(或者,更确切地说,它连接到一个不再存在的元素)。
Here's a simple jsfiddlethat does exactly the same as your code, except that it prints the selected file names in a different element than the element the input is in. And it works (in WebKit, anyway)
这是一个简单的 jsfiddle,与您的代码完全相同,除了它在与输入元素不同的元素中打印选定的文件名。并且它可以工作(无论如何在 WebKit 中)
Here's further proof(I basically copied your code, and only added a line to re-register the event listener after the modification of wrapper.innerHTML
)
这里进一步证明(我基本上是复制你的代码,只加了一行修改后重新注册事件监听器wrapper.innerHTML
)
So, the change
event doesfire for each change, but the input that's being observed is removed by the use of innerHTML
on the input's parent element.
因此,change
事件不火的每一个变化,但是这被观察的输入是通过使用删除innerHTML
输入的父元素。
I honestly don't know whether this is a legitimate browser bug or not. It makes sense for innerHTML
to "overwrite" the existing input element, yet the browser is smart enough to not not reset the input's value, so you'd think listeners would stick around too… so… well, it's confusing
老实说,我不知道这是否是一个合法的浏览器错误。innerHTML
“覆盖”现有的输入元素是有意义的,但浏览器足够聪明,不会重置输入的值,所以你会认为听众也会留下来......所以......好吧,这很令人困惑
回答by fundon
If you want to upload twice, clear file input value
如果要上传两次,清除文件输入值
$('input[type="file"]').val(null);
回答by edgarhsanchez
I'm not sure why but none of the answers to this old question are all that simple. Here's the way to do this easily today...
我不知道为什么,但这个老问题的答案都不是那么简单。这是今天轻松做到这一点的方法......
with jquery...
用 jquery...
$('#myfileinputfieldid')[0].onchange = function(e) {
//do something with e. Like write an image to a canvas or make a yummy cup of coffee
e.target.value = '';
};
that's it after you have changed the value to something other than the file that was selected the next time the file input is clicked the onchange event will fire.
这就是在您将值更改为下一次单击文件输入时选择的文件以外的值之后,onchange 事件将触发。
回答by user3082420
Instead of using onchange use oninput event
而不是使用 onchange 使用 oninput 事件
$scope.ShowIcon = function (input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#iAIcon')
.attr('src', e.target.result)
};
reader.readAsDataURL(input.files[0]);
}
}
回答by A H Bensiali
ok well according to @Flambino the input is being re-rendered. For whatever reason this may be, for me its irrelevant. The $.on('change', callback) functionality is lost.
好吧,根据@Flambino,输入正在重新渲染。无论出于何种原因,这对我来说都是无关紧要的。$.on('change', callback) 功能丢失。
Try using .delegate function which I absolutely love! http://api.jquery.com/delegate/
尝试使用我非常喜欢的 .delegate 函数! http://api.jquery.com/delegate/
Ok so delegate is exactly the same, it just tells jquery if there is an element rendered on screen with a particular handle, attach a functionality to it.
好吧,委托是完全一样的,它只是告诉 jquery 是否有一个元素呈现在屏幕上并带有特定的句柄,为其附加一个功能。
So even if the element is re-rendered, it will still keep to function.
因此,即使元素被重新渲染,它仍将继续发挥作用。
$(document).delegate('.file_upload_btn', 'change', function(){});
You may think this is a throw away function & say whats the difference but this has saved me a lot of time on projects.
您可能认为这是一个丢弃功能并说有什么区别,但这为我节省了很多项目时间。
回答by Kevin J
I got the .change callback to fire on every new file by reassigning the .change function at the end of its own callback:
通过在自己的回调结束时重新分配 .change 函数,我让 .change 回调在每个新文件上触发:
$('#myfileinputfieldid').change(function (event) {
scope.processFile(event.target.files[0]);
});
scope.processFile = function(fileStruct) {
doStuff;
// Reassign the onchange callback.
$('#myfileinputfieldid').change(function (event) {
scope.processFile(event.target.files[0]);
});
};
回答by Андрей Палкин
In my case i use ajax to upload file. I just clear the value of input with onclick event handler.
就我而言,我使用 ajax 上传文件。我只是使用 onclick 事件处理程序清除 input 的值。
$('#myFile').click(function(e) {e.target.value = '';});
$('#myFile').change(function(e) {
var file = e.target.value;
var formdata = new FormData();
formdata.append('file', file, 'somefile');
$.ajax({
type: 'POST',
url: './uploadFile',
data: formdata,
processData: false,
contentType: false,
success: function(data){
}
});
});
回答by Phil LaNasa
None of the above worked for me, I actually had to create a new "dummy" file input field each time it was changed - allowing me to capture the change event again.
以上都不适合我,实际上每次更改时我都必须创建一个新的“虚拟”文件输入字段 - 允许我再次捕获更改事件。
The process for me was:
我的过程是:
OnChange - move file input to another element - create a new file input to capture the change event again
OnChange - 将文件输入移动到另一个元素 - 创建一个新的文件输入以再次捕获更改事件
回答by Chetan Nellekeri
addEventListener wont work for IE8(Not sure about IE9 onwards). We need to use attachEvent listiner. If you need cross browser support then use this
addEventListener 不适用于 IE8(不确定 IE9 以后)。我们需要使用 attachEvent 列表器。如果您需要跨浏览器支持,请使用此
if (!inputfile.addEventListener) {
inputfile.attachEvent("onclick", setCheckedValues); //IE8
}else {
inputfile.addEventListener("click", setCheckedValues, false); //Other browser
}