Answers:
虽然这不是直接的解决方案,但也很糟糕,它仅(就我所测试的而言)与onfocus一起使用(需要相当大的事件限制),您可以使用以下方法实现此目的:
document.body.onfocus = function(){ /*rock it*/ }
这样做的好处是,您可以在文件事件中及时附加/分离它,并且它对于隐藏的输入似乎也可以很好地工作(如果您对the脚的默认输入类型使用可视化解决方法,则可以肯定地得到了回报。文件')。之后,您只需要确定输入值是否已更改。
一个例子:
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')
}
实际观看:http : //jsfiddle.net/Shiboe/yuK3r/6/
可悲的是,它似乎只能在webkit浏览器上使用。也许其他人可以找出firefox / IE解决方案
addEventListener("focus",fn,{once: true})
。但是我无法使用document.body.addEventListener
..我完全不知道为什么。相反,我得到与相同的结果window.addEventListener
。
mousemove
事件上window.document
,除了要听focus
上window
似乎到处工作(至少在现代浏览器,我不关心过去十年的残骸)。基本上,任何交互事件都可以用于此任务,该事件被打开的文件打开对话框阻止。
因此,自从我提出了一个新颖的解决方案以来,我将对此表示怀疑。我有一个渐进式Web应用程序,允许用户捕获照片和视频并上传它们。我们在可能的情况下使用WebRTC,但对于支持较少的设备,请改用HTML5文件选择器*咳嗽Safari咳嗽*。如果您专门在使用本机相机直接捕获照片/视频的Android / iOS移动Web应用程序上工作,那么这是我遇到的最好的解决方案。
这个问题的症结在于,页面加载时,file
is是null
,但是当用户打开对话框并按“ Cancel”时,file
is仍然是null
,因此它没有“更改”,因此不会触发“更改”事件。对于台式机来说,这还算不错,因为大多数台式机UI并不依赖于知道何时调用取消,但是带动相机捕获照片/视频的移动UI却非常依赖于何时按下取消。
我最初使用该document.body.onfocus
事件来检测用户何时从文件选择器返回,并且该方法适用于大多数设备,但是iOS 11.3破坏了该事件,因为未触发该事件。
我的解决方案是* shudder *,以测量CPU时序以确定当前页面是在前台还是在后台。在移动设备上,将处理时间分配给当前位于前台的应用程序。当摄像机可见时,它将占用CPU时间并降低浏览器的优先级。我们需要做的就是测量给页面多少处理时间,当相机启动时,我们的可用时间将大大减少。关闭相机(取消或取消相机)后,我们的可用时间会重新增加。
我们可以通过使用setTimeout()
X毫秒来调用回调来测量CPU时序,然后测量实际调用它所花费的时间。浏览器永远不会在X毫秒之后精确地调用它,但是如果可以关闭,则我们必须处于前台。如果浏览器距离很远(比要求的速度慢10倍以上),那么我们必须在后台。这样的基本实现是这样的:
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);
});
}
我在最新版本的iOS和Android上对此进行了测试,通过在<input />
元素上设置属性来调出本机相机。
<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />
这实际上比我预期的要好得多。它通过请求在25毫秒内调用计时器来运行10次试用。然后,它测量实际调用所需的时间,如果10次尝试的平均时间少于50毫秒,则我们假定必须处于前台并且相机已关闭。如果大于50毫秒,那么我们必须仍然在后台并且应该继续等待。
我之所以使用setTimeout()
它,不是setInterval()
因为后者可以将多个调用排入队列,这些调用彼此之后立即执行。这可能会大大增加数据中的噪声,因此我坚持这样做,setTimeout()
尽管这样做要复杂一些。
这些特殊的数字对我来说效果很好,尽管我至少看到过一次相机过早熄灭的情况。我认为这是因为相机打开速度可能很慢,并且该设备可能在实际变为背景之前进行了10次试用。添加更多试用版或等待25至50毫秒才能启动此功能,可能是一种解决方法。
不幸的是,这对于台式机浏览器实际上并不起作用。从理论上讲,相同的技巧是可能的,因为它们的确将当前页面置于后台页面之上。但是,许多台式机具有足够的资源,即使在后台运行时也可以保持页面全速运行,因此这种策略在实践中实际上并不起作用。
很少有人提到我确实探索过的另一种解决方案是模拟FileList
。我们开始null
在<input />
后,如果用户打开摄像头,并取消他们回来null
,这是不发生变化,没有事件将触发。一种解决方案是将一个虚拟文件分配给<input />
页面开始处,因此将设置为null
将触发适当事件的更改。
不幸的是,没有正式的方法来创建FileList
,并且<input />
元素FileList
特别需要a ,并且除了以外将不接受任何其他值null
。自然地,FileList
对象不能直接构造,可以解决一些旧的安全问题,这些问题显然不再相关。保持<input />
元素外部唯一的方法是利用一种黑客技术,该技术通过复制粘贴数据来伪造可能包含一个FileList
对象的剪贴板事件(您基本上是在伪造一个拖放文件, -您的网站事件)。这在Firefox中是可行的,但对于iOS Safari则不可行,因此在我的特定用例中不可行。
不用说这显然是荒谬的。网页的关键用户界面元素已更改为零通知这一事实简直是可笑的。这确实是规范中的错误,因为它原本不打算用于全屏媒体捕获UI,并且从技术上讲,不触发“ change”事件是技术上的规范。
但是,浏览器供应商能否认识到这一现实?这可以通过新的“完成”事件来解决,即使没有发生更改也可以触发该事件,或者无论如何您都可以触发“更改”。是的,这违背了规范,但是对于我而言,在JavaScript方面简化变更事件是微不足道的,但是从根本上来说,不可能发明自己的“完成”事件。如果不保证浏览器的状态,即使我的解决方案实际上也只是试探法。
就目前而言,此API从根本上讲不适用于移动设备,而且我认为相对简单的浏览器更改可能会使Web开发人员无限轻松地“摆脱肥皂盒”。
/* 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 */
}
});
else
过您的陈述是否得到过评估?
这些解决方案大多数都不适合我。
问题是,你永远不知道这将触发事件的拳头,是它click
还是它change
?您不能假设任何顺序,因为它可能取决于浏览器的实现。
至少在Opera和Chrome浏览器中(2015年末)click
是在文件“填充”输入之前触发的,因此files.length != 0
直到延迟click
触发之后,您才知道它的长度change
。
这是代码:
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);
};
});
只需听一下click事件。
在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!');
}
});
您可以在此处查看它的运行情况:http : //jsfiddle.net/T3Vwz
如果选择与以前相同的文件,然后单击“取消”,则可以捕获取消:在这种情况下。
您可以这样做:
<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>
最简单的方法是检查临时内存中是否有文件。如果您希望每次用户单击文件输入时都获得更改事件,则可以触发它。
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
}
});
如果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);
});
现在,我们正在听屏幕上的触摸以进行相同的文件检查。我非常有信心,取消并取消此活动指示器后,用户的手指将很快出现在屏幕上。
也可以将活动指示器添加到文件输入更改事件上,但是在移动设备上,选择图片和更改事件触发之间通常会间隔几秒钟,因此在活动指示器上显示活动指示器要好得多该过程的开始。
我找到了这个属性,它是最简单的。
if ($('#selectedFile')[0].files.length > 1)
{
// Clicked on 'open' with file
} else {
// Clicked on 'cancel'
}
这selectedFile
是一个input type=file
。
就我而言,我必须在用户选择图像时隐藏提交按钮。
这就是我的想法:
$(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和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 */
通常,mousemove事件可以解决问题,但如果用户单击并导致以下事件:
...我们不会收到mousemove事件,因此没有取消回调。此外,如果用户取消第二个对话框并移动鼠标,我们将获得2个取消回调。幸运的是,在两种情况下,特殊的jQuery focusIn事件都会冒泡到文档中,从而帮助我们避免了这种情况。唯一的限制是是否有一个阻止focusIn事件。
mousemove
事件document
。没问题,不移动鼠标或仅使用键盘选择文件。我不得不更换mousemove
被keydown
检测尽早取消,但不能“太早”,当对话框仍然开放。
我看到我的回应会很过时,但永远不会少。我面临着同样的问题。所以这是我的解决方案。最有用的代码是KGA的代码。但是它不能完全正常工作,并且有点复杂。但是我简化了。
同样,主要的麻烦制造者是这样一个事实,即“改变”事件并不是在聚焦后立即发生的,因此我们必须等待一段时间。
“ #appendfile”-用户单击以添加新文件。Href获得焦点事件。
$("#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);
});
您只能在有限的情况下检测到此情况。具体来说,在chrome中,如果之前选择了文件,然后单击了文件对话框,然后单击取消,Chrome将清除文件并触发onChange事件。
https://code.google.com/p/chromium/issues/detail?id=2508
在这种情况下,您可以通过处理onChange事件并检查files属性来检测到此情况。
以下似乎适用于我(在台式机,Windows上):
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;
}
这确实使用了angularjs $ q,但是如果需要,您应该可以将其替换为任何其他Promise框架。
在IE11,Edge,Chrome,Firefox上进行了测试,但由于它不会触发Focus事件,因此它似乎无法在Android Tablet上的Chrome上运行。
该file
型字段,令人沮丧的,并没有很多的事件(模糊是可爱的)响应。我看到很多人都在建议change
面向解决方案,但他们却被否决了。
change
确实有效,但是它有一个主要缺陷(与我们要发生的事情相比)。
重新加载包含文件字段的页面时,请打开该框,然后按“取消”。令人沮丧的是,没有任何变化。
我选择做的是在门控状态下加载。
section#after-image
在我的情况下,表单a的下一部分从视图中隐藏了。当我的file field
变化,上传按钮显示。成功上传后,section#after-image
显示。change
此取消会触发该事件,然后我可以(并确实)重新隐藏我的上传按钮,直到选择了正确的文件为止。我很幸运,这个门控状态已经是我表单的设计。您不需要使用相同的样式,只需先隐藏上传按钮,然后进行更改即可,将隐藏字段或javascript变量设置为可以在提交时监视的内容。
在与字段进行交互之前,我尝试更改files [0]的值。这与onchange无关。
因此,change
可以,至少可以达到我们想要的效果。出于明显的原因,文件字段是安全的,但是出于良好意图的开发人员的考虑而感到沮丧。
这不符合我的目的,但是您可能能够onclick
加载警告提示(不是alert()
,因为它会暂停页面处理),并在触发更改且files [0]为null时将其隐藏。如果未触发更改,则div保持其状态。
有一种方法可以做到这一点(添加回调或解决某些延迟/承诺实现而不是alert()
调用):
var result = null;
$('<input type="file" />')
.on('change', function () {
result = this.files[0];
alert('selected!');
})
.click();
setTimeout(function () {
$(document).one('mousemove', function () {
if (!result) {
alert('cancelled');
}
});
}, 1000);
工作原理:打开文件选择对话框时,文档不接收鼠标指针事件。有1000毫秒的延迟,以允许对话框实际出现并阻止浏览器窗口。已在Chrome和Firefox中检查(仅Windows)。
当然,但这不是检测已取消对话框的可靠方法。不过,可能会为您改善一些UI行为。
这是我的解决方案,使用文件输入焦点(不使用任何计时器)
var fileInputSelectionInitiated = false;
function fileInputAnimationStart() {
fileInputSelectionInitiated = true;
if (!$("#image-selector-area-icon").hasClass("fa-spin"))
$("#image-selector-area-icon").addClass("fa-spin");
if (!$("#image-selector-button-icon").hasClass("fa-spin"))
$("#image-selector-button-icon").addClass("fa-spin");
}
function fileInputAnimationStop() {
fileInputSelectionInitiated = false;
if ($("#image-selector-area-icon").hasClass("fa-spin"))
$("#image-selector-area-icon").removeClass("fa-spin");
if ($("#image-selector-button-icon").hasClass("fa-spin"))
$("#image-selector-button-icon").removeClass("fa-spin");
}
$("#image-selector-area-wrapper").click(function (e) {
$("#fileinput").focus();
$("#fileinput").click();
});
$("#preview-image-wrapper").click(function (e) {
$("#fileinput").focus();
$("#fileinput").click();
});
$("#fileinput").click(function (e) {
fileInputAnimationStart();
});
$("#fileinput").focus(function (e) {
fileInputAnimationStop();
});
$("#fileinput").change(function(e) {
// ...
}
Error: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 }
这充其量是很棘手的,但这是我的解决方案的一个有效示例,用于检测用户是否已上传文件,并且仅允许他们在已上传文件的情况下继续操作。
基本上隐藏Continue
,Save
,Proceed
或者无论你的按钮。然后在JavaScript中获取文件名。如果文件名没有值,则不显示Continue
按钮。如果确实有值,则显示按钮。如果他们首先上传文件,然后尝试上传其他文件,然后单击“取消”,这也可以使用。
这是代码。
HTML:
<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>
JavaScript:
$('#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');
}
});
CSS:
.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;
}
对于CSS来说,很多目的是使每个人都可以访问网站和按钮。将按钮样式设置为任意样式。
好吧,这并不能完全回答您的问题。我的假设是,您有一个场景,当您添加文件输入并调用文件选择时,如果用户单击“取消”,则只需删除输入。
如果是这种情况,那么:为什么要添加空文件输入?
即时创建一个,但仅在填写后将其添加到DOM。就像这样:
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();
因此,我在此处动态创建<input type =“ file” />,绑定到它的change事件,然后立即调用click。仅当用户选择一个文件并单击“确定”时才会触发on change,否则输入将不会添加到DOM,因此不会提交。
这里的工作示例:https : //jsfiddle.net/69g0Lxno/3/
如果您已经需要JQuery,则此解决方案可能会起作用(这与我实际需要的代码完全相同,尽管使用Promise只是强制代码等待文件选择解决):
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();
});
此线程中有几种建议的解决方案,这种难以检测用户单击文件选择框上的“取消”按钮的问题是影响很多人的问题。
事实是,没有100%可靠的方法来检测用户是否单击了文件选择框上的“取消”按钮。但是,有一些方法可以可靠地检测用户是否已将文件添加到输入文件中。所以这是这个答案的基本策略!
我之所以决定添加此答案,是因为其他答案显然不适用于大多数浏览器或无法在移动设备上使用。
简而言之,代码基于三点:
为了更好地理解,请查看下面的代码以及说明。
[...]
<button type="button" onclick="addIptFl();">ADD INPUT FILE!</button>
<span id="ipt_fl_parent"></span>
[...]
function dynIptFl(jqElInst, funcsObj) {
if (typeof funcsObj === "undefined" || funcsObj === "") {
funcsObj = {};
}
if (funcsObj.hasOwnProperty("before")) {
if (!funcsObj["before"].hasOwnProperty("args")) {
funcsObj["before"]["args"] = [];
}
funcsObj["before"]["func"].apply(this, funcsObj["before"]["args"]);
}
var jqElInstFl = jqElInst.find("input[type=file]");
// NOTE: Open the file selection box via js. By Questor
jqElInstFl.trigger("click");
// NOTE: This event is triggered if the user selects a file. By Questor
jqElInstFl.on("change", {funcsObj: funcsObj}, function(e) {
// NOTE: With the strategy below we avoid problems with other unwanted events
// that may be associated with the DOM element. By Questor
e.preventDefault();
var funcsObj = e.data.funcsObj;
if (funcsObj.hasOwnProperty("after")) {
if (!funcsObj["after"].hasOwnProperty("args")) {
funcsObj["after"]["args"] = [];
}
funcsObj["after"]["func"].apply(this, funcsObj["after"]["args"]);
}
});
}
function remIptFl() {
// NOTE: Remove the input file. By Questor
$("#ipt_fl_parent").empty();
}
function addIptFl() {
function addBefore(someArgs0, someArgs1) {
// NOTE: All the logic here happens just before the file selection box opens.
// By Questor
// SOME CODE HERE!
}
function addAfter(someArgs0, someArgs1) {
// NOTE: All the logic here happens only if the user adds a file. By Questor
// SOME CODE HERE!
$("#ipt_fl_parent").prepend(jqElInst);
}
// NOTE: The input file is hidden as all manipulation must be done via js.
// By Questor
var jqElInst = $('\
<span>\
<button type="button" onclick="remIptFl();">REMOVE INPUT FILE!</button>\
<input type="file" name="input_fl_nm" style="display: block;">\
</span>\
');
var funcsObj = {
before: {
func: addBefore,
args: [someArgs0, someArgs1]
},
after: {
func: addAfter,
// NOTE: The instance with the input file ("jqElInst") could be passed
// here instead of using the context of the "addIptFl()" function. That
// way "addBefore()" and "addAfter()" will not need to be inside "addIptFl()",
// for example. By Questor
args: [someArgs0, someArgs1]
}
};
dynIptFl(jqElInst, funcsObj);
}
谢谢!= D
我们实现了如下所示的角度。
<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" />
我已经使用了jQuery,显然每个人都可以使用valina JS(根据要求)。
$("#file_to_upload").change(function() {
if (this.files.length) {
alert('file choosen');
} else {
alert('file NOT choosen');
}
});
.change()
如果用户在文件选择器上单击“取消”,则不会可靠地调用该函数。
enter code here
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
<div id="cancel01">
<button>Cancel</button>
</div>
<div id="cancel02">
<button>Cancel</button>
</div>
<div id="cancel03">
<button>Cancel</button>
</div>
<form>
<input type="file" name="name" placeholder="Name" />
</form>
<script>
const nameInput = document.querySelector('input[type="file"]');
/******
*The below code if for How to detect when cancel is clicked on file input
******/
nameInput.addEventListener('keydown', e => {
/******
*If the cancel button is clicked,then you should change the input file value to empty
******/
if (e.key == 'Backspace' || e.code == 'Backspace' || e.keyCode == 8) {
console.log(e);
/******
*The below code will delete the file path
******/
nameInput.value = '';
}
});
</script>
</body>
</html>
注意:此代码不会检测取消,它提供了一种方法,可以避免在人们尝试检测取消的常见情况下检测到取消的需要。
我在这里寻找隐藏输入的文件上传解决方案时,我相信这是寻找一种检测文件输入取消的方法的最常见原因(打开文件对话框->如果选择了文件,然后运行一些代码,否则什么也不做),这是我的解决方案:
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'));
});
}
请注意,如果未选择任何文件,则第一行将仅返回一次,selectFile()
或者再次调用(或者fileSelectorResolve()
从其他地方调用)。
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 ...
}
您可以在输入字段上进行jquery更改侦听器,并通过该字段的值检测用户取消或关闭了上载窗口。
这是一个例子:
//when upload button change
$('#upload_btn').change(function(){
//get uploaded file
var file = this.files[0];
//if user choosed a file
if(file){
//upload file or perform your desired functiuonality
}else{
//user click cancel or close the upload window
}
});
e.target.files