Arquivo de julho de 2007

Enviando vários arquivos sem exibir input file

Dia 06/07/2007 na lista Webstandards-br foi questionado como o gmail fazia, para que sem o input file, fosse enviado arquivo. Porém isso só acontecia no IE, no Firefox era um input normal.O pessoal deu uma olhada no código e concluiu que no IE funcionava algo como:

JavaScript:
  1. document.getElementById('InputFile').click();

Porém no Firefox isso não funciona. Não querendo entrar no mérito de qual navegador está certo, pensei em um modo de driblar isso e o resultando acabou resultando neste artigo.

Como fazer

Minha idéia para contornar isso é utilizar um input que fique transparente e colocar uma imagem no fundo do elemento onde esse input está! Veja que não podemos esconder o input, pois ele precisa ser clicado, mas sem que o usuário perceba. Então vamos ao HTML básico:

HTML:
  1. <form method="post" enctype="multipart/form-data" id="UploadForm">
  2. <p id="uploadButton"> <input id="inputFile" name="inputFile" size="1" type="file" /></p>
  3.  
  4. </form>

Temos um div chamado uploadButton, que conterá a imagem de fundo e o input que fará a coisa acontecer.

Adicionamos um pouco de CSS:

CSS:
  1. #inputFile {
  2.   float: right;
  3.   opacity: 0;
  4.   filter: alpha(opacity=0);
  5. }
  6. #uploadButton {
  7.   width:88px;
  8.   height:20px;
  9.   background:url("adicionar.jpg") no-repeat;
  10.   float:left;
  11.   margin: 0 20px 0 0;
  12. }
  13. #files {
  14.   clear:both;
  15. }

Veja que no #inputFile definimos opacity, para funciona no Firefox e um filter para ficar transparente no IE. O #files veremos pra que serve daqui a pouco.

Fazendo a mágica acontecer com javascript

Utilizei a jQuery por pura comodidade, mas poderia facilmente ser feito na mão. Na verdade para enviar um arquivo precisariamos do javascript apenas para exibir o nome do arquivo em algum lugar. Mas como queremos fazer o upload de vários arquivos:

JavaScript:
  1. var InputCount=1;
  2. $(function() {
  3. $("#UploadForm").append("&lt;ul id='files'&gt;&lt;/ul&gt;");
  4. $("#inputFile").change( function() { newFile(); } );
  5. });
  6. function newFile() {
  7. $("#files").append("&lt;li&gt;" + $("#inputFile").val() + "&lt;/li&gt;");
  8. $("#inputFile").hide();
  9. $("#inputFile").clone().appendTo("#uploadButton");
  10. $("#inputFile").attr("id", "inputFile" + InputCount);
  11. $("#inputFile" + InputCount).attr("name", "inputFile" + InputCount);
  12. InputCount++;
  13. $("#inputFile").change( function() { newFile(); } );
  14. $("#inputFile").val("");
  15. $("#inputFile").show();
  16. }

Para ver tudo funcionando acesse o exemplo.
Para finalizar ainda seria necessário adicionar um botão de submit e tratar o retorno no servidor. Porém isso não será tratado aqui!

Após escrever todo o exemplo e o artigo, resolvi testar no IE6 (o que devia ter sido feito antes) e percebi que não funcionava o filtro da opacidade, apesar de tudo dar certo no IE 5 e no IE 7. Estou com o tempo curto e se você descobrir como resolver, poste um comentário.