简体   繁体   English

为什么单击 FireFox 中的按钮会打开文件打开对话框两次

[英]Why file open dialog opens twice on clicking the button in FireFox

I have a file <input> field and a <span> decorates the input field:我有一个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>

While the behavior of this is as I suppose in Chrome and Safari , FireFox opens two file input dialogs on clicking the button(span) .虽然这种行为与我在ChromeSafari 中的假设一样,但FireFox在单击button(span)打开两个file input dialogs

Why could happen so?为什么会这样?

I assume, that file input field is invisible and only access to it is through the span with a button behavior.我假设,该文件输入字段是不可见的,只有通过具有按钮行为的跨度才能访问它。

Update:更新:

if I put the <input> outside of <span> it behaves normally.如果我将<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 JSFiddle

but why on inside position it does not?但为什么在inside position它没有呢?

It is because of some kind of event propagation mess这是因为某种事件传播混乱

<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>

And

function doOpen(event){
    event = event || window.event;
    if(event.target.id != 'filechose_button'){
        filechose_button.click();
    }
}

Demo: Fiddle演示:小提琴

It is because of event propagation.这是因为事件传播。 When you click on the span, click event is raised and in the click handler you have called click on input type="file" so it is calling twice.当您单击跨度时,会引发单击事件,并且在单击处理程序中您已调用单击输入类型 =“文件”,因此它会调用两次。

If you will try following code it would not raise propagated event.如果您尝试以下代码,它不会引发传播事件。

<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>

For more information visit this link有关更多信息,请访问此链接

You should play with this to get more understanding on event propagation.您应该使用它来对事件传播有更多的了解。

I needed to use "unbind click" for my code to work normally.我需要使用“取消绑定点击”让我的代码正常工作。

$("#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();
});

Seems like there could still be situations where the DOM bounces the event around, so the technique of hiding an input field and programming it to click is susceptible.似乎仍然存在 DOM 反弹事件的情况,因此隐藏输入字段并将其编程为单击的技术很容易受到影响。 I am now working on a modal dialog in an AngularJS app (designed to be used either on mobile with cordova or on a desktop browser) that needs to launch a file picker, where this phenomena happens and none of the above techniques helped.我现在正在 AngularJS 应用程序(设计为在移动设备上使用cordova 或在桌面浏览器上使用)中的模态对话框需要启动文件选择器,这种现象发生并且上述技术都没有帮助。

When I place console logs on the bouncing event, it shows that the echo can arrive up to 1 second after the original click.当我将控制台日志放在弹跳事件上时,它显示回声最多可以在原始点击后 1 秒到达。

Following is a solution that overcomes it by creating a small stack of events, and eliminating duplicates that happen within 2 seconds.以下是通过创建一小堆事件并消除 2 秒内发生的重复来克服它的解决方案。

Cheers, Z.干杯,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>

I have a complex application and from some reason the following jQuery selector:我有一个复杂的应用程序,并且出于某种原因有以下 jQuery 选择器:

$('input[type=file]')

returned two jQuery elements instead of one.返回两个 jQuery 元素而不是一个。

So calling:所以调用:

$('input[type=file]').trigger('click')

Triggered two file dialog box opened one after the other.触发两个文件对话框一个接一个打开。

To solve this, I only applied the click trigger on the first element为了解决这个问题,我只在第一个元素上应用了点击触发器

$($('input[type=file]').get(0)).trigger('click');

In addition I used unbind and stopped event propagation, here is the full code:另外我使用了解除绑定和停止事件传播,这里是完整的代码:

$('#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
    });

I have a file <input> field and a <span> decorates the input field:我有一个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>

While the behavior of this is as I suppose in Chrome and Safari , FireFox opens two file input dialogs on clicking the button(span) .尽管此行为与我在ChromeSafari中的预期相同,但FireFox在单击button(span)打开两个file input dialogs

Why could happen so?为什么会这样呢?

I assume, that file input field is invisible and only access to it is through the span with a button behavior.我假设文件输入字段是不可见的,并且只能通过具有按钮行为的跨度来访问它。

Update:更新:

if I put the <input> outside of <span> it behaves normally.如果将<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 JSFiddle

but why on inside position it does not?但是为什么在inside position却没有呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM