Html 如何检测在文件输入时单击取消?

Html 如何检测在文件输入时单击取消?,html,file,input,Html,File,Input,如何检测用户何时使用html文件输入取消文件输入 onChange允许我检测他们何时选择文件,但我也想知道他们何时取消(关闭文件选择对话框而不选择任何内容)。您不能 “文件”对话框的结果不会显示在浏览器中。当您选择一个文件并单击“打开/取消”时,输入元素应失去焦点,即模糊。假设输入的初始值为空,则模糊处理程序中的任何非空值都将表示OK,空值表示Cancel 更新:隐藏输入时,模糊不会触发。因此,不能在基于IFRAME的上载中使用此技巧,除非您想临时显示输入,如果您选择与前面相同的文件并单击“取消

如何检测用户何时使用html文件输入取消文件输入

onChange允许我检测他们何时选择文件,但我也想知道他们何时取消(关闭文件选择对话框而不选择任何内容)。

您不能


“文件”对话框的结果不会显示在浏览器中。

当您选择一个文件并单击“打开/取消”时,
输入
元素应失去焦点,即
模糊
。假设
输入
的初始
为空,则
模糊
处理程序中的任何非空值都将表示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');
}