为啥文件打开对话框在单击 FireFox 中的按钮时打开两次
Posted
技术标签:
【中文标题】为啥文件打开对话框在单击 FireFox 中的按钮时打开两次【英文标题】:Why file open dialog opens twice on clicking the button in FireFox为什么文件打开对话框在单击 FireFox 中的按钮时打开两次 【发布时间】:2013-04-23 22:28:12 【问题描述】:我有一个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 会打开 两个 @987654325 @点击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"/>
JSFiddle
但是为什么inside position
没有呢?
【问题讨论】:
您是否尝试过将 onclick 放在输入标签中? 从 span 中移除 onclick 并查看.. 不,但我应该做输入可渲染(它打破了跨度元素) 我相信 filechose_button.click() 正在这样做。删除 .click() 删除文件chose_button.click() 使按钮失效。 【参考方案1】:这是因为某种事件传播混乱
<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
【讨论】:
当我将输入放在 span 之外时,我不需要任何 js。但无论如何,谢谢你的帮助! @static 这也是我的建议,但从 cmets 我认为这对你来说不可行【参考方案2】:这是因为事件传播。当您单击跨度时,会引发单击事件,并且在单击处理程序中您调用了单击输入类型 =“文件”,因此它会调用两次。
如果您尝试以下代码,它不会引发传播事件。
<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
您应该使用它来进一步了解事件传播。
【讨论】:
@NullPointer 欢迎。很高兴能帮助你。 :)【参考方案3】:我有一个复杂的应用程序,出于某种原因,下面的 jQuery 选择器:
$('input[type=file]')
返回两个 jQuery 元素而不是一个。
呼唤:
$('input[type=file]').trigger('click')
触发两个文件一个接一个打开的对话框。
为了解决这个问题,我只在第一个元素上应用了点击触发器
$($('input[type=file]').get(0)).trigger('click');
另外我使用了 unbind 并停止了事件传播,这里是完整的代码:
$('#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
);
【讨论】:
【参考方案4】:似乎仍然存在 DOM 反弹事件的情况,因此隐藏输入字段并将其编程为单击的技术很容易受到影响。我现在正在开发一个 AngularJS 应用程序(设计用于带有 cordova 的移动设备或桌面浏览器)中的模式对话框,该应用程序需要启动一个文件选择器,在这种情况下会发生这种现象并且上述技术都没有帮助。
当我在弹跳事件上放置控制台日志时,它显示回声可以在原始点击后最多 1 秒到达。
Following 是一种解决方案,它通过创建一小堆事件并消除在 2 秒内发生的重复事件来克服它。
干杯, Z.
<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>
【讨论】:
【参考方案5】:我需要使用“取消绑定点击”才能让我的代码正常工作。
$("#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();
);
【讨论】:
以上是关于为啥文件打开对话框在单击 FireFox 中的按钮时打开两次的主要内容,如果未能解决你的问题,请参考以下文章