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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16292487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 04:05:22  来源:igfitidea点击:

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

javascriptfirefoxfile-uploadhtml-inputinput-field

提问by static

I have a file <input> fieldand 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 Chromeand Safari, FireFoxopens twofile input dialogson clicking the button(span).

虽然这种行为是因为我在想的ChromeSafari浏览器火狐打开2file input dialogs上点击button(span)

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 positionit does not?

但为什么inside position不呢?

回答by Arun P Johny

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

演示:小提琴

回答by Jenish Rabadiya

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.

您应该使用它来对事件传播有更多的了解。

回答by Genivan Silveira de Souza

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

回答by zi88

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

似乎仍然存在 DOM 反弹事件的情况,因此隐藏输入字段并将其编程为单击的技术很容易受到影响。我现在正在 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>

回答by Uri Lukach

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
    });