1

Primefaces 5

I have <input type="file" class="ui-fileupload-choose> in code to upload the files. This input-Tag is generated automatically from a PrimeFaces component <p:fileUpload>. I want to hide the button for input element and use my own styled button for upload.

So this is the styled button.

<input type="button" onclick="$('#formId\\:uploaderId .ui-fileupload-choose input').click();">

This does function in FF, Chrome and IE9, 10, 11. But in IE8 nothing happens in upload phase. The "choose file" dialog is shown. The generated input file has JQuery change event. I believe that this event will not be called, because if I click on input file button it goes in all browsers.

I've tried

<input type="button" onclick="$('#formId\\:uploaderId .ui-fileupload-choose input').click(); #formId\\:uploaderId ui-fileupload-choose input').trigger('change');">

but it doesn't help.

Also I've tried

$('#formId\\:uploaderId .ui-fileupload-choose input').change(function () {
    // Cause the change() event
    // to be fired in IE8 et. al.
    //some checks against recursion.
     alert("I'm in change");
    $('#formId\\:uploaderId .ui-fileupload-choose input').change();               
});

The function in change is called but it doesn't help either.

What can I do in this situation ?

Tony
  • 2,266
  • 4
  • 33
  • 54
  • 1
    Magically I'm working on the same problem now in one of my projects. It seems that it's a security issue, where the click/change of the input file is being triggered manually by javascript onclick. The process of initiating the upload is taking a place but the request is never being sent! I'll update this question if I find some elegant solution! currently I'm checking for the browser version, if it's IE I'm changing the way the upload is done. – Hatem Alimam Nov 05 '14 at 08:54
  • @HatemAlimam Cool, thank you for your comment. I will use the `` without changes if there is no simple solution to this problem. Good luck ! – Tony Nov 05 '14 at 08:59
  • I just found another [question](http://stackoverflow.com/questions/12556988/ie-doesnt-allow-to-upload-the-file-if-it-is-not-keybord-click-for-input-type-f) on that topic, I think I was right it's a security thing for IE :( – Hatem Alimam Nov 05 '14 at 09:01
  • I found this answer interesting and as you say it has something to do with security. [link](http://stackoverflow.com/a/13994676/2023524) – Tony Nov 05 '14 at 10:09

3 Answers3

1

This is due to a security restriction in IE.

When there's <input type="file"/> which has either of

  • display:none
  • visbilty:hidden
  • opacity: 0

IE blocks the request to upload the file if it's being called manually (javascript click).

In PrimeFaces case the input file has opacity: 0.

Here's how the input file looks like without the CSS extra flavours:

fileupload

The work around is to move that input file outside p:fileUpload component so it can loose the CSS roles, and append it to a span or div with button styling, that would result an actual click on the file input.

Button

<span class="btn btn-primary btn-file">
   <i class="fa fa-upload"></i> Upload File
</span>

javascript

$(document).ready(function() {
   $('.ui-fileupload-buttonbar span input[type=file]').addClass('uploadBtn');
   $('.btn-file').append($('.uploadBtn'));
});

Something link this:

append1

Now to get it to look nice and work in the same time on all browsers including IE, some CSS should be added. First ignore the first two CSS classes btn btn-primary (colors, padding etc..)

The btn-file is the custom trick:

.btn-file {
   position: relative;
   overflow: hidden;
 }

 .btn-file input[type=file] {
    position: absolute;
    top: 0;
    right: 0;
    min-width: 100%;
    min-height: 100%;
    font-size: 999px;
    text-align: right;
    filter: alpha(opacity=0);
    opacity: 0;        
    cursor: inherit;
    display: block;
 } 

The final result is a button with input file in the background:

final

The p:fileUpload component should be hidden:

<p:fileUpload style="display: none" />

In order to display the error messages you can use onchange event for that input file:

$('.uploadBtn').change(function() {
   var a = $('.ui-fileupload-content').html(); var b = $('#editUserUploadMessages').html(a);
})

Where #editUserUploadMessages is a div containing all the messages.

Finally hide the other uploaded files:

#editUserUploadMessages .ui-fileupload-files {
     display: none;
}

You can find a small example on github and a Demo

Hatem Alimam
  • 9,968
  • 4
  • 44
  • 56
  • Wow, thank you for your answer. I need also errors as (fileSize and fileType) to be shown, so I posted additional solution. – Tony Nov 05 '14 at 13:11
  • 1
    I have added also a way to show the messages, retry the demo, upload a non image file :) – Hatem Alimam Nov 05 '14 at 13:37
1

Additional solution to an excellent answer of Hatem. It is using this SO answer.

You can use html tag <label> to forward the click to input buton.

<h:form id="formId" >
 <style>

 #formId\:uploaderId .ui-fileupload-buttonbar {
    position: absolute;  
    left: -10000px;
 }

 #formId\:uploaderId .ui-fileupload-content {
    border: none;
 }
 </style>

 <p:fileUpload id="uploaderId" mode="advanced" auto="true" allowTypes="..." fileLimit="...">


 <label for="formId:uploaderId_input">
    <span class="fa fa-upload" />    
 </label>
</h:form>

This way the errors will be shown at point where <p:fileUpload> is included.

Community
  • 1
  • 1
Tony
  • 2,266
  • 4
  • 33
  • 54
-2
  1. add style display:none to input type="file"
  2. create new text box and button at the position of input type file
  3. create js function when click your button that click the button of file upload