4

I 'crafted' this piece of jQuery + html to accomplish the following:

There is a placeholder image that user can click, which causes a file selection dialog to open. Once a file is selected, the corresponding multipart form is uploaded to the server. I am trying to imitate AJAX behavior for this file upload, so I also use an invisible iframe to receive server response.

Let me present the code first, so it would be easier to explain the problem

jQuery("#myInput").change(function () {  // Submit form upon file selection
   // alert("myInput.val() = " + $('#myInput').val());  // alert 1
    $('#form1').submit();
   // alert("myInput.val() = " + $('#myInput').val());  // alert 2
});

<form id="form1" action="/do_upload.php" method="post" enctype="multipart/form-data" target="target_frame">
<input id="myInput" type="file" name="userfile" /><br>
</form>
<img src="/img/placeholder.png" onclick="$('#myInput').click();" >

<iframe id="target_frame" name="target_frame" src="#" style="width:0;height:0;border:0px solid #fff;"></iframe>

The code works perfectly on new Chrome/Firefox/Safari. (Interestingly it even works if I set visibility: hidden; on myInput. So apparently that's not much of a security concern). However both IE 9 and 10 show the same behavior: clicking the image brings up the dialog successfully, the file path is correctly set in "alert 1", but it is gone in "alert 2", and the form doesn't get submitted. On the other hand, clicking directly on the browse button of myInput properly brings up the dialog and submits the form.

I am absolutely confused by how this behavior can even be possible! Any suggestions on how to fight off the annoying IE would be greatly appreciated :)

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Alex M
  • 175
  • 1
  • 9
  • 2
    any errors in the console? – John Dvorak Oct 08 '13 at 04:59
  • Can you try changing the _.click()_ to _.change()_ in the image's onclick callback i.e. **onclick="$('#myInput').change();"**? – Gurminder Singh Oct 08 '13 at 05:32
  • The `click` approach always worked bad for me. After some research how other library solved it I choose the approach to overlay the image with the `input` element, setting its the opacity value so that it is not visible by human but not invisible with respect of the `opacity` value. So the user always does a real click. – t.niese Oct 08 '13 at 05:33
  • @JanDvorak - No errors or warnings in the console. Thanks for forcing me to discover that there are developer tools in IE! :) – Alex M Oct 08 '13 at 22:16
  • @GurminderSingh - Using .change() actually doesn't bring up the file selection dialog at all, but immediately triggers my jQuery("#myInput").change() handler. – Alex M Oct 08 '13 at 22:18
  • @t.niese - Yes, I have read about overlaying transparent input=file element over customs elements. My question would be this: Is it possible to style that transparent element so that its size matches any given image, and so that clicking at any point of the image would produce a click on the element? I was impressed by how Facebook handles image uploads. I'd like to be able to more or less emulate what they do, but I am afraid that I won't be able to figure out how their code works.. Haven't even tried yet :) – Alex M Oct 08 '13 at 22:26
  • 1
    All this clever jQuery and yet still using an inline `onclick` handler. Why? – Sparky Oct 09 '13 at 04:07
  • @Sparky - Haha, I suppose it's for the sake of brevity :) It doesn't really make any difference, does it? I suppose inline JS breaks the possible nice separation of jQuery code from HTML. Is that what you mean? – Alex M Oct 09 '13 at 14:47
  • 1
    Yes. IMO, inline JavaScript handlers are ugly and unnecessary when an alternative is available. It's also easier to read/troubleshoot when fully separated. – Sparky Oct 09 '13 at 15:35
  • @Sparky - Fair enough. Point taken. I am extremely new to web development, so I am still to form good programming practices :) – Alex M Oct 09 '13 at 15:44

2 Answers2

0

I believe it is a safety feature of IE. it won't allow you to access the name attribute of the file input if using another trigger.

You must click the file input for IE and not use another trigger.

Edit: A workaround IE clears input[type="file"] on submit

Community
  • 1
  • 1
luke2012
  • 1,724
  • 1
  • 13
  • 20
  • But I think logically simply hiding the input=file element and emulating a click on it is not a security issue. Indeed the user will see the file dialog and will choose whatever file they want, or dismiss the dialog. I think that's why my code works in most modern browsers except IE. The real security issue would be to allow programmatically setting the value of the input=file element. So in fact in my case $('#myInput').val('any_value') doesn't affect the value in any browser. Which is totally logical :) – Alex M Oct 08 '13 at 22:31
  • Someone can loop this and becomes irritating shit. Thats why IE doesn't allows. Also unsafe because js on other servers or iframes might confuse user to snatch their personal data – DiLDoST Apr 08 '23 at 15:01
0

I decided to go with the method of overlaying a transparent file element over my image. My inspiration came from this page: https://coderwall.com/p/uer3ow. Here is my HTML and CSS that were required:

.file_loader {
    position: relative;
    overflow: hidden;
    border: solid gray 1px;
    margin: auto;
    width: 300px;
    height: 400px;  
}

.file_loader .hidden_file {
    display: block;
    background: white;
    font-size: 80px;
    height: 100%;
    width: 100%;
    opacity: 0;
    position: absolute;
    top: 0;
    left: 0;
}

.placeholder {
    height: 100%;
    width: 100%;
}

<div class="file_loader">
    <img src="/img/placeholder.png" id="placeholder1" class="placeholder" >
    <form id="form1" action="/do_upload.php" method="post" enctype="multipart/form-data" target="target_frame">
    <input id="myInput" class="hidden_file" type="file" name="userfile" /><br>
    </form>
</div>

As you can see the height and width of the "file_loader" class enforce the dimensions of the placeholder image and of the transparent input=file element overlay. There is one thing in this CSS that is truly brilliant, and it came from that link. I'm talking about setting the very large font-size for file element. It is key for making it work in IE, because it happens to make the "Browse" button so gigantic that it fills the whole placeholder. Without changing the font-size, in IE you would end up with only part of the image being able to bring up file dialog (the rest would be a transparent text field). I'll point out that in Chrome/Firefox/Safari this font-size trick is unnecessary, as the whole file element is clickable there.

Alex M
  • 175
  • 1
  • 9