5

I'm working on an image uploader app, and everything is working great except for one bug, which is occurring only in Chrome. I've stripped down the problem to one callback which isn't going through.

The issue is that a .fadeOut callback to a .click() trigger isn't triggering. I've recreated a simplified version in a fiddle which is linked below. The first click starts the fadeOut, and when the fadeOut is finished, the .click trigger doesn't happen. Clicking a second time Does then trigger the trigger. Any ideas why?

HTML:

<div><input type="file" name="image_file" id="image_file"/></div>

<div class="overlay_wrap">
    Overlast
</div>

<a id="click" href="">Click</a>

jQuery:

$(document).ready(function() {
    $("#click").click(function(event) {
        event.preventDefault();
        $('.overlay_wrap').fadeOut(1000, function(event){
            $('#image_file').trigger('click');
        });
    });
});

http://jsfiddle.net/gg2a7/5/

Thank you for the help!

EDIT: Had the old Fiddle link, changed.

Kelderic
  • 6,502
  • 8
  • 46
  • 85
  • 1
    Somehow placing the trigger() in the callback seems to defer the event, and it's looks like it's Chrome's security stopping the event, probably because it thinks it's not user generated or something like that. Just taking it out of the callback solves the issue, and testing with a regular setTimeout seems to have the same issue, so it has something to do with the defering of the trigger(). There's an answer [**here**](http://stackoverflow.com/questions/210643/in-javascript-can-i-make-a-click-event-fire-programmatically-for-a-file-input) that deals with a somewhat similar issue. – adeneo Mar 04 '13 at 21:00
  • Here's [another answer](http://stackoverflow.com/questions/12134014/how-can-i-programmatically-open-the-file-picker-with-javascript) that supports what adeneo is saying. – John S Mar 04 '13 at 21:11
  • So there is no way around this? – Kelderic Mar 04 '13 at 21:13

2 Answers2

2

Sadly, this will not work. It all has to do with timing/threading functions inside browsers.

The core of the problem is this: The <input type="file" /> can not be opened programmatically (Loads of questions on SO / stuff on Google about it). It's not only Chrome; Firefox is showing a message that a pop-up is blocked, Safari will block it too, and in IE the form will not submit.

The reason behind this is because it's a potential security risk. Only a user action can result inside opening this <input type="file" />. Because of the .fadeOut(), the browser doesn't recognize this as a user event anymore. Now we're getting back to the timing/threading of the browsers, since this does work. There isn't any delegation, nor another thread/timeout of some sort that prevents the dialog from opening.

$("#click").click(function(event) {
    event.preventDefault();
    $('#image_file').trigger('click');
});

JSFiddle.

To show that it is actually the <input type="file" />, here's an example with <input type="button" /> that does work:

HTML

<input type="button" name="image_file" id="image_file" value="type='button'" />

JS

$("#click").click(function(event) {
        event.preventDefault();
        $('.overlay_wrap').fadeOut(1000, function(){
            $('#image_file').trigger('click');
        });
    });

    $('#image_file').click(function() {
         alert('ok');   
    });

JSFiddle.

Long story short: You can't do this with a fade effect. You can simply open the dialog and hide the element, but that's all there is to it.

$("#click").click(function(event) {
    event.preventDefault();
    $('.overlay_wrap').hide();
    $('#image_file').trigger('click');
});

JSFiddle.

Community
  • 1
  • 1
MarcoK
  • 6,090
  • 2
  • 28
  • 40
  • That's disappointing but I can work around it. The odd thing is that when I tested on Firefox and IE 10 it worked. FF gave me and "do you want to allow popups for this site", and IE10 gave no warnings at all, just worked. – Kelderic Mar 06 '13 at 19:09
  • This was driving me nuts. I was very confused why it worked in an event callback but not a callback inside of an event callback. Looks like I'll have to work around it. – Dex Jan 20 '15 at 09:37
0

Change your $('.overlay_wrap').fadeOut(1000,complete) to

$('.overlay_wrap').fadeOut(1000);
complete();
MIIB
  • 1,849
  • 10
  • 21
  • 2
    This won't wait for the fade to finish before executing the complete function. – VVV Mar 04 '13 at 21:00