Shi*_*boe 43
虽然不是一个直接的解决方案,也是不好的,因为它只是(据我测试过)与onfocus一起使用(需要一个非常有限的事件阻塞),你可以通过以下方式实现它:
document.body.onfocus = function(){ /*rock it*/ }
Run Code Online (Sandbox Code Playgroud)
有什么好处的,就是你可以及时附加/分离它与文件事件,它似乎也可以正常使用隐藏的输入(如果你使用一个视觉解决方法的蹩脚的默认输入类型='一个明确的振作'文件').之后,您只需要确定输入值是否已更改.
一个例子:
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')
}
Run Code Online (Sandbox Code Playgroud)
看到它在行动:http://jsfiddle.net/Shiboe/yuK3r/6/
可悲的是,它似乎只适用于webkit浏览器.也许其他人可以找出firefox/IE解决方案
Ode*_*ded 19
你不能.
文件对话框的结果不会向浏览器公开.
新的文件系统访问 API将使我们的生活再次变得轻松:)
try {
const [fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
// ...
}
catch (e) {
console.log('Cancelled, no file selected');
}
Run Code Online (Sandbox Code Playgroud)
浏览器支持非常有限(2021 年 1 月)。该示例代码在 Chrome 桌面 86 中运行良好。
小智 8
/* 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 */
}
});
Run Code Online (Sandbox Code Playgroud)
因此,自从我提出了一个新颖的解决方案以来,我将对此表示怀疑。我有一个渐进式Web应用程序,允许用户捕获照片和视频并上传它们。我们会尽可能使用WebRTC,但对于支持较少的设备,请使用HTML5文件选择器*咳嗽Safari咳嗽*。如果您专门在使用本机相机直接捕获照片/视频的Android / iOS移动Web应用程序上工作,那么这是我遇到的最好的解决方案。
这个问题的症结在于,当页面加载时,fileis null,但是当用户打开对话框并按“ Cancel”时,fileis仍然是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);
});
}
Run Code Online (Sandbox Code Playgroud)
我在最新版本的iOS和Android上对此进行了测试,通过在<input />元素上设置属性来调出本机相机。
<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />
Run Code Online (Sandbox Code Playgroud)
这实际上比我预期的要好得多。它通过请求在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开发人员无限轻松地“摆脱肥皂盒”。
当您选择一个文件并单击打开/取消时,该input元素应该失去焦点blur.假设初始value的input是空的,在你的任何非空值的blur处理程序将指示OK,和一个空值将意味着取消.
更新:隐藏blur时不会触发input.所以不能使用这个技巧与基于IFRAME的上传,除非你想暂时显示input.
只需听一下点击事件.
以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!');
}
});
Run Code Online (Sandbox Code Playgroud)
你可以在这里看到它:http://jsfiddle.net/T3Vwz
小智 5
这些解决方案大多数都不适合我。
问题是,你永远不知道这将触发事件的拳头,是它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);
};
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
95467 次 |
| 最近记录: |