问题
I have a file <input> field
and a <span>
decorates the input field:
<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)
.
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.
<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
but why on inside position
it does not?
回答1:
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
回答2:
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.
回答3:
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.
When I place console logs on the bouncing event, it shows that the echo can arrive up to 1 second after the original click.
Following is a solution that overcomes it by creating a small stack of events, and eliminating duplicates that happen within 2 seconds.
Cheers, 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>
回答4:
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();
});
回答5:
I have a complex application and from some reason the following jQuery selector:
$('input[type=file]')
returned two jQuery elements instead of one.
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
});
来源:https://stackoverflow.com/questions/16292487/why-file-open-dialog-opens-twice-on-clicking-the-button-in-firefox