Html 如何检测在文件输入时单击取消?
如何检测用户何时使用html文件输入取消文件输入 onChange允许我检测他们何时选择文件,但我也想知道他们何时取消(关闭文件选择对话框而不选择任何内容)。您不能Html 如何检测在文件输入时单击取消?,html,file,input,Html,File,Input,如何检测用户何时使用html文件输入取消文件输入 onChange允许我检测他们何时选择文件,但我也想知道他们何时取消(关闭文件选择对话框而不选择任何内容)。您不能 “文件”对话框的结果不会显示在浏览器中。当您选择一个文件并单击“打开/取消”时,输入元素应失去焦点,即模糊。假设输入的初始值为空,则模糊处理程序中的任何非空值都将表示OK,空值表示Cancel 更新:隐藏输入时,模糊不会触发。因此,不能在基于IFRAME的上载中使用此技巧,除非您想临时显示输入,如果您选择与前面相同的文件并单击“取消
“文件”对话框的结果不会显示在浏览器中。当您选择一个文件并单击“打开/取消”时,
输入
元素应失去焦点,即模糊
。假设输入
的初始值
为空,则模糊
处理程序中的任何非空值都将表示OK,空值表示Cancel
更新:隐藏
输入时,模糊
不会触发。因此,不能在基于IFRAME的上载中使用此技巧,除非您想临时显示输入
,如果您选择与前面相同的文件并单击“取消”:在这种情况下,您可以捕获取消
您可以这样做:
<input type="file" id="myinputfile"/>
<script>
document.getElementById('myinputfile').addEventListener('change', myMethod, false);
function myMethod(evt) {
var files = evt.target.files;
f= files[0];
if (f==undefined) {
// the user has clicked on cancel
}
else if (f.name.match(".*\.jpg")|| f.name.match(".*\.png")) {
//.... the user has choosen an image file
var reader = new FileReader();
reader.onload = function(evt) {
try {
myimage.src=evt.target.result;
...
} catch (err) {
...
}
};
}
reader.readAsDataURL(f);
</script>
document.getElementById('myinputfile')。addEventListener('change',myMethod,false);
函数myMethod(evt){
var files=evt.target.files;
f=文件[0];
如果(f==未定义){
//用户已单击“取消”
}
else if(f.name.match(“.\.jpg”)| | f.name.match(“.\.png”)){
//..用户已选择图像文件
var reader=new FileReader();
reader.onload=函数(evt){
试一试{
myimage.src=evt.target.result;
...
}捕捉(错误){
...
}
};
}
reader.readAsDataURL(f);
有一种黑客方法可以做到这一点(添加回调或解决一些延迟/承诺实现,而不是alert()
调用):
var结果=null;
$('')
.on('change',function(){
结果=this.files[0];
警报('selected!');
})
。单击();
setTimeout(函数(){
$(文档).one('mousemove',函数(){
如果(!结果){
警报(“取消”);
}
});
}, 1000);
工作原理:当文件选择对话框打开时,文档不接收鼠标指针事件。有1000毫秒的延迟允许对话框实际出现并阻止浏览器窗口。在Chrome和Firefox中检查(仅限Windows)
当然,这并不是检测取消对话框的可靠方法。不过,这可能会改善您的某些UI行为。虽然不是一个直接的解决方案,但也不好,因为它只能(据我测试)与onfocus一起工作(需要非常有限的事件阻止),您可以通过以下方式实现:
document.body.onfocus = function(){ /*rock it*/ }
这样做的好处是,您可以通过file事件及时附加/分离它,而且它似乎也可以很好地处理隐藏的输入(如果您对蹩脚的默认输入type='file'使用视觉解决方案,这是一个明确的好处)。之后,您只需确定输入值是否发生了更改
例如:
var godzilla = document.getElementById('godzilla')
godzilla.onclick = charge
function charge()
{
document.body.onfocus = roar
console.log('chargin')
}
function roar()
{
if(godzilla.value.length) alert('ROAR! FILES!')
else alert('*empty wheeze*')
document.body.onfocus = null
console.log('depleted')
}
在行动中看到它:
不幸的是,它似乎只适用于webkit浏览器。也许其他人可以找到firefox/IE解决方案。在我的情况下,当用户选择图像时,我不得不隐藏提交按钮
这就是我想说的:
$(document).on('click', '#image-field', function(e) {
$('.submit-button').prop('disabled', true)
})
$(document).on('focus', '#image-field'), function(e) {
$('.submit-button').prop('disabled', false)
})
#image field
是我的文件选择器。当某人单击它时,我会禁用表单提交按钮。关键是,当文件对话框关闭时-无论他们选择文件还是取消-#image field
重新获得焦点,所以我会监听该事件
更新
我发现,这在safari和poltergeist/phantomjs中不起作用。如果您想实现它,请将此信息考虑在内。Shiboe的解决方案是一个不错的解决方案,如果它在移动webkit上起作用,但它不起作用。我能想到的是在文件输入窗口打开时向某个dom对象添加一个mousemove事件侦听器打开,像这样:
$('.upload-progress').mousemove(function() {
checkForFiles(this);
});
checkForFiles = function(me) {
var filefield = $('#myfileinput');
var files = filefield.get(0).files;
if (files == undefined || files[0] == undefined) $(me).remove(); // user cancelled the upload
};
当文件对话框打开时,页面上的mousemove事件被阻止,当其关闭时,会检查文件输入中是否有任何文件。在我的情况下,我需要一个活动指示器阻止事件,直到文件上载,所以我只想在取消时删除指示器
然而,这并不能解决移动设备的问题,因为没有鼠标可以移动。我的解决方案还不够完美,但我认为已经足够好了
$('.upload-progress').bind('touchstart', function() {
checkForFiles(this);
});
现在,我们正在听屏幕上的触摸,以执行相同的文件检查。我很有信心,在取消并关闭此活动指示灯后,用户的手指将很快被放到屏幕上
您也可以在文件输入更改事件上添加活动指示器,但在移动设备上,在选择图像和触发更改事件之间通常会有几秒钟的延迟,因此在流程开始时显示活动指示器会更好。只需听一下单击事件即可
以下是Shiboe的示例,下面是一个jQuery示例:
var godzilla = $('#godzilla');
var godzillaBtn = $('#godzilla-btn');
godzillaBtn.on('click', function(){
godzilla.trigger('click');
});
godzilla.on('change click', function(){
if (godzilla.val() != '') {
$('#state').html('You have chosen a Mech!');
} else {
$('#state').html('Choose your Mech!');
}
});
您可以在这里看到它的作用:结合Shiboe和alx的解决方案,我得到了最可靠的代码:
var selector = $('<input/>')
.attr({ /* just for example, use your own attributes */
"id": "FilesSelector",
"name": "File",
"type": "file",
"contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/
})
.on("click.filesSelector", function () {
/* do some magic here, e.g. invoke callback for selection begin */
var cancelled = false; /* need this because .one calls handler once for each event type */
setTimeout(function () {
$(document).one("mousemove.filesSelector focusin.filesSelector", function () {
/* namespace is optional */
if (selector.val().length === 0 && !cancelled) {
cancelled = true; /* prevent double cancel */
/* that's the point of cancel, */
}
});
}, 1); /* 1 is enough as we just need to delay until first available tick */
})
.on("change.filesSelector", function () {
/* do some magic here, e.g. invoke callback for successful selection */
})
.appendTo(yourHolder).end(); /* just for example */
var选择器=$(“”)
.attr({/*例如,使用您自己的属性*/
“id”:“文件选择器”,
“名称”:“文件”,
“类型”:“文件”,
“contentEditable”:“false”/*如果您通过标签“单击”输入,这将阻止IE7-8仅将插入符号设置到文件输入的文本字段中*/
})
.on(“单击.fileselector”),函数(){
/*在这里做一些魔术,例如调用回调以开始选择*/
var cancelled=false;/*需要此选项,因为每个事件类型都需要调用一次处理程序*/
setTimeout(函数(){
$(document).one(“mousemove.fileselector focusin.fileselector”,函数(){
/*名称空间是可选的*/
if(selector.val().length==0&&!已取消){
取消=真;/*防止双重取消*/
/*这就是取消的重点*/
}
});
}
var selector = $('<input/>')
.attr({ /* just for example, use your own attributes */
"id": "FilesSelector",
"name": "File",
"type": "file",
"contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/
})
.on("click.filesSelector", function () {
/* do some magic here, e.g. invoke callback for selection begin */
var cancelled = false; /* need this because .one calls handler once for each event type */
setTimeout(function () {
$(document).one("mousemove.filesSelector focusin.filesSelector", function () {
/* namespace is optional */
if (selector.val().length === 0 && !cancelled) {
cancelled = true; /* prevent double cancel */
/* that's the point of cancel, */
}
});
}, 1); /* 1 is enough as we just need to delay until first available tick */
})
.on("change.filesSelector", function () {
/* do some magic here, e.g. invoke callback for successful selection */
})
.appendTo(yourHolder).end(); /* just for example */
$("#appendfile").one("focusin", function () {
// no matter - user uploaded file or canceled,
// appendfile gets focus
// change doesn't come instantly after focus, so we have to wait for some time
// wrapper represents an element where a new file input is placed into
setTimeout(function(){
if (wrapper.find("input.fileinput").val() != "") {
// user has uploaded some file
// add your logic for new file here
}
else {
// user canceled file upload
// you have to remove a fileinput element from DOM
}
}, 900);
});
/* Tested on Google Chrome */
$("input[type=file]").bind("change", function() {
var selected_file_name = $(this).val();
if ( selected_file_name.length > 0 ) {
/* Some file selected */
}
else {
/* No file selected or cancel/close
dialog button clicked */
/* If user has select a file before,
when they submit, it will treated as
no file selected */
}
});
var inputfile = $("#yourid");
inputfile.on("change click", function(ev){
if (ev.originalEvent != null){
console.log("OK clicked");
}
document.body.onfocus = function(){
document.body.onfocus = null;
setTimeout(function(){
if (inputfile.val().length === 0) console.log("Cancel clicked");
}, 1000);
};
});
<div class="container">
<div class="row">
<input class="file-input" type="file" accept="image/*" name="fileUpload" id="fileUpload" capture="camera">
<label for="fileUpload" id="file-upload-btn">Capture or Upload Photo</label>
</div>
<div class="row padding-top-two-em">
<input class="btn btn-success hidden" id="accept-btn" type="submit" value="Accept & Continue"/>
<button class="btn btn-danger">Back</button>
</div></div>
$('#fileUpload').change(function () {
var fileName = $('#fileUpload').val();
if (fileName != "") {
$('#file-upload-btn').html(fileName);
$('#accept-btn').removeClass('hidden').addClass('show');
} else {
$('#file-upload-btn').html("Upload File");
$('#accept-btn').addClass('hidden');
}
});
.file-input {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.file-input + label {
font-size: 1.25em;
font-weight: normal;
color: white;
background-color: blue;
display: inline-block;
padding: 5px;
}
.file-input:focus + label,
.file-input + label:hover {
background-color: red;
}
.file-input + label {
cursor: pointer;
}
.file-input + label * {
pointer-events: none;
}
var openFile = function (mimeType, fileExtension) {
var defer = $q.defer();
var uploadInput = document.createElement("input");
uploadInput.type = 'file';
uploadInput.accept = '.' + fileExtension + ',' + mimeType;
var hasActivated = false;
var hasChangedBeenCalled = false;
var hasFocusBeenCalled = false;
var focusCallback = function () {
if (hasActivated) {
hasFocusBeenCalled = true;
document.removeEventListener('focus', focusCallback, true);
setTimeout(function () {
if (!hasChangedBeenCalled) {
uploadInput.removeEventListener('change', changedCallback, true);
defer.resolve(null);
}
}, 300);
}
};
var changedCallback = function () {
uploadInput.removeEventListener('change', changedCallback, true);
if (!hasFocusBeenCalled) {
document.removeEventListener('focus', focusCallback, true);
}
hasChangedBeenCalled = true;
if (uploadInput.files.length === 1) {
//File picked
var reader = new FileReader();
reader.onload = function (e) {
defer.resolve(e.target.result);
};
reader.readAsText(uploadInput.files[0]);
}
else {
defer.resolve(null);
}
};
document.addEventListener('focus', focusCallback, true); //Detect cancel
uploadInput.addEventListener('change', changedCallback, true); //Detect when a file is picked
uploadInput.click();
hasActivated = true;
return defer.promise;
}
if ($('#selectedFile')[0].files.length > 1)
{
// Clicked on 'open' with file
} else {
// Clicked on 'cancel'
}
var fileInput = $("<input type='file' name='files' style='display: none' />");
fileInput.bind("change", function() {
if (fileInput.val() !== null) {
// if has value add it to DOM
$("#files").append(fileInput);
}
}).click();
var yourFileInput = $("#yourFileInput");
yourFileInput.on('mouseup', function() {
$(this).trigger("change");
}).on('change', function() {
if (this.files.length) {
//User chose a picture
} else {
//User clicked cancel
}
});
var fileInput = $("#fileInput");
if (fileInput.is(":hover") {
//open
} else {
}
function waitForCameraDismiss() {
const REQUESTED_DELAY_MS = 25;
const ALLOWED_MARGIN_OF_ERROR_MS = 25;
const MAX_REASONABLE_DELAY_MS =
REQUESTED_DELAY_MS + ALLOWED_MARGIN_OF_ERROR_MS;
const MAX_TRIALS_TO_RECORD = 10;
const triggerDelays = [];
let lastTriggerTime = Date.now();
return new Promise((resolve) => {
const evtTimer = () => {
// Add the time since the last run
const now = Date.now();
triggerDelays.push(now - lastTriggerTime);
lastTriggerTime = now;
// Wait until we have enough trials before interpreting them.
if (triggerDelays.length < MAX_TRIALS_TO_RECORD) {
window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
return;
}
// Only maintain the last few event delays as trials so as not
// to penalize a long time in the camera and to avoid exploding
// memory.
if (triggerDelays.length > MAX_TRIALS_TO_RECORD) {
triggerDelays.shift();
}
// Compute the average of all trials. If it is outside the
// acceptable margin of error, then the user must have the
// camera open. If it is within the margin of error, then the
// user must have dismissed the camera and returned to the page.
const averageDelay =
triggerDelays.reduce((l, r) => l + r) / triggerDelays.length
if (averageDelay < MAX_REASONABLE_DELAY_MS) {
// Beyond any reasonable doubt, the user has returned from the
// camera
resolve();
} else {
// Probably not returned from camera, run another trial.
window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
}
};
window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
});
}
<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />
function file_click() {
document.body.onfocus = () => {
setTimeout(_=>{
let file_input = document.getElementById('file_input');
if (!file_input.value) alert('please choose file ')
else alert(file_input.value)
document.body.onfocus = null
},100)
}
}
await new Promise(resolve => {
const input = $("<input type='file'/>");
input.on('change', function() {
resolve($(this).val());
});
$('body').one('focus', '*', e => {
resolve(null);
e.stopPropagation();
});
input.click();
var fileSelectorResolve;
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.addEventListener('input', function(){
fileSelectorResolve(this.files[0]);
fileSelectorResolve = null;
fileSelector.value = '';
});
function selectFile(){
if(fileSelectorResolve){
fileSelectorResolve();
fileSelectorResolve = null;
}
return new Promise(function(resolve){
fileSelectorResolve = resolve;
fileSelector.dispatchEvent(new MouseEvent('click'));
});
}
async function logFileName(){
const file = await selectFile();
if(!file) return;
console.log(file.name);
}
async function uploadFile(){
const file = await selectFile();
if(!file) return;
// ... make an ajax call here to upload the file ...
}
<input type="file" formControlName="FileUpload" click)="handleFileInput($event.target.files)" />
/>
this.uploadPanel = false;
handleFileInput(files: FileList) {
this.fileToUpload = files.item(0);
console.log("ggg" + files);
this.uploadPanel = true;
}
@HostListener("window:focus", ["$event"])
onFocus(event: FocusEvent): void {
if (this.uploadPanel == true) {
console.log("cancel clicked")
this.addSlot
.get("FileUpload")
.setValidators([
Validators.required,
FileValidator.validate,
requiredFileType("png")
]);
this.addSlot.get("FileUpload").updateValueAndValidity();
}
}
<input type="file" id="file_to_upload" name="file_to_upload" />
$("#file_to_upload").change(function() {
if (this.files.length) {
alert('file choosen');
} else {
alert('file NOT choosen');
}
});
try {
const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
// ...
}
catch (e) {
console.log('Cancelled, no file selected');
}