我有file <input> field
和<span>
装饰输入字段:
<span class="span5 btn btn-primary btn-file" id="chose_files_btn" onclick="filechose_button.click()">chose files
<input id="filechose_button" type="file" name="fileData" size="1" style="display: none"/>
</span>
虽然我认为此行为与 Chrome 和 Safari 一样, FireFox 会打开两个 {{ 1}}点击file input dialogs
。
为什么会这样?
我假设,该文件输入字段是不可见的,只有通过具有按钮行为的跨度才能访问它。
如果我将button(span)
置于<input>
之外,则表现正常。
<span>
但为什么 <span class="span5 btn btn-primary btn-file" id="chose_files_btn" onclick="filechose_button.click()">chose files</span>
<input id="filechose_button" type="file" name="fileData" size="1" style="display: none"/>
没有呢?
答案 0 :(得分:7)
这是因为某种事件传播混乱
<span class="span5 btn btn-primary btn-file" id="chose_files_btn" onclick="doOpen(event)">chose files
<input id="filechose_button" type="file" name="fileData" size="1" style="display: none"/>
</span>
并且
function doOpen(event){
event = event || window.event;
if(event.target.id != 'filechose_button'){
filechose_button.click();
}
}
演示:Fiddle
答案 1 :(得分:5)
这是因为事件传播。单击跨度时,会单击事件并在您调用的单击处理程序中单击输入type =“file”,以便它调用两次。
如果您尝试使用以下代码,则不会引发传播事件。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#chose_files_btn").click(function(event){
filechose_button.click();
});
$("#filechose_button").click(function(event){
event.stopPropagation();
});
});
</script>
<span class="span5 btn btn-primary btn-file" id="chose_files_btn">chose files
<input id="filechose_button" type="file" name="fileData" size="1" style="display: none"/>
</span>
有关详细信息,请访问this link
你应该玩这个来更好地理解事件传播。
答案 2 :(得分:0)
我需要使用“解除绑定点击”才能使我的代码正常工作。
$("#chose_files_btn").unbind( "click" );
$("#chose_files_btn").click(function(event){
$("#filechose_button).click();
});
$("#filechose_button").unbind( "click" );
$("#filechose_button").click(function(event){
event.stopPropagation();
});
答案 3 :(得分:0)
似乎仍然存在DOM反弹事件的情况,因此隐藏输入字段并将其编程为单击的技术很容易受到影响。我现在正在开发一个AngularJS应用程序中的模式对话框(设计用于带有cordova的移动设备或桌面浏览器上),需要启动文件选择器,这种情况发生,上述技术都没有帮助。
当我在弹跳事件上放置控制台日志时,它会显示原始点击后回声最多可以达到1秒。
以下是一种解决方案,通过创建一小堆事件来克服它,并消除在2秒内发生的重复。
干杯, ž。
<div id="fileInputImagePicker-container" onclick="openJustOnce( event )">
<script>
var eventRecords=[];
const MAX_BOUNCE_DELAY = 2000;
function addEvent( event ){
eventRecords.push( {id: event.target.id, time: Date.now()})
}
function isBounceEvent( event ){
var ret = false, now = Date.now(), latestTime=0;
for( var i=0; i < eventRecords.length && !ret; i++ ){
var record = eventRecords[ i ];
if( record.time > latestTime ) latestTime = record.time;
if( record.id === event.target.id && (now - record.time) < MAX_BOUNCE_DELAY ){
ret = true;
//console.log('BOUNCE EVENT, record=', JSON.stringify(record), ' event=', event);
}
}
if( now - latestTime > MAX_BOUNCE_DELAY ) eventRecords = [];
if( !ret ) addEvent( event );
return ret;
}
function openJustOnce( event ) {
//console.log( "container event, event=", event, " event.target=", event.target, " now=", Date.now() );
if( isBounceEvent(event) ) {
event.stopPropagation();
event.preventDefault();
//console.log( "BLOCK THIS EVENT" );
} else {
fileInputImagePicker.click();
//console.log( "DONT BLOCK" );
}
}
</script>
<input type="file" accept="image/*" id="fileInputImagePicker" style="display:none" />
</div>
答案 4 :(得分:0)
我有一个复杂的应用程序,并且出于某种原因使用了以下jQuery选择器:
$('input[type=file]')
返回了两个jQuery元素,而不是一个。
所以打电话:
$('input[type=file]').trigger('click')
触发的两个文件对话框一个接一个地打开。
为解决此问题,我仅在第一个元素上应用了点击触发器
$($('input[type=file]').get(0)).trigger('click');
此外,我使用了取消绑定和停止事件传播的功能,这是完整的代码:
$('#uploadFile').click(function(evt) {
evt.stopPropagation();
evt.preventDefault();
evt = evt || window.event;
if(evt.target.id == 'uploadFile'){
$($('input[type=file]').get(0)).trigger('click');
}
});
$(':file').unbind();
$(':file').on('change', function(evt) {
// extra non-relevant code
});