Problema com script que cuztomiza input file [Resolvido]


(Ailime Rodrigues) #1

Estou com um problema e não estou atinando para resolver. Gostaria da ajuda de vcs se possível.

Tenho um formulário com um campo input file, ao qual foi estilizado para mudar sua aparência com jquery e css. Até tudo bem, funcionando normalmente. Neste formulário fiz as validações com o jquery validade.
Os demais campos do formulário(input, select, textarea) a validação funciona direitinho (dá a mensagem de erro e os campos ficam com a borda vermelha) porém no input file a validação funciona até, mas o css não pega nele, não muda a cor da borda. Já verifiquei o css está tudo normal. Acredito que seja alguma alteração que tenha que fazer no script mas não estou conseguindo.

Alguém saberia me informar??
Obrigada desde já.

segue a baixo o código do script que "customiza" o input file.

<script type="text/javascript">
;(function( $ ) {
 // Browser supports HTML5 multiple file?
 var multipleSupport = typeof $('<input/>')[0].multiple !== 'undefined',
     isIE = /msie/i.test( navigator.userAgent );
 $.fn.customFile = function() {
   return this.each(function() {
     var $file = $(this).addClass('customfile'), // the original file input
         $wrap = $('<div class="customfile-wrap">'),
         $input = $('<input type="text" class="customfile-filename" />'),
         // Button that will be used in non-IE browsers
         $button = $('<button type="button" class="customfile-upload">Selecionar</button>'),
         // Hack for IE
         $label = $('<label class="customfile-upload" for="'+ $file[0].id +'">Selecionar</label>');
     // Hide by shifting to the left so we
     // can still trigger events
     $file.css({
       position: 'absolute',
       left: '-9999px'
     });
     $wrap.insertAfter( $file )
       .append( $file, $input, ( isIE ? $label : $button ) );
     // Prevent focus
     $file.attr('tabIndex', -1);
     $button.attr('tabIndex', -1);
     $button.click(function () {
       $file.focus().click(); // Open dialog
     });
     $file.change(function() {
       var files = [], fileArr, filename;
       // If multiple is supported then extract
       // all filenames from the file array
       if ( multipleSupport ) {
         fileArr = $file[0].files;
         for ( var i = 0, len = fileArr.length; i < len; i++ ) {
           files.push( fileArr[i].name );
         }
         filename = files.join(', ');
       // If not supported then just take the value
       // and remove the path to just show the filename
       } else {
         filename = $file.val().split('\\').pop();
       }
       $input.val( filename ) // Set the value
         .attr('title', filename) // Show filename in title tootlip
         .focus(); // Regain focus
     });
     $input.on({
       blur: function() { $file.trigger('blur'); },
       keydown: function( e ) {
         if ( e.which === 13 ) { // Enter
           if ( !isIE ) { $file.trigger('click'); }
         } else if ( e.which === 8 || e.which === 46 ) { // Backspace & Del
           // On some browsers the value is read-only
           // with this trick we remove the old input and add
           // a clean clone with all the original events attached
           $file.replaceWith( $file = $file.clone( true ) );
           $file.trigger('change');
           $input.val('');
         } else if ( e.which === 9 ){ // TAB
           return;
         } else { // All other keys
           return false;
         }
       }
     });
   });
 };
 // Old browser fallback
 if ( !multipleSupport ) {
   $( document ).on('change', 'input.customfile', function() {
     var $this = $(this),
         // Create a unique ID so we
         // can attach the label to the input
         uniqId = 'customfile_'+ (new Date()).getTime(),
         $wrap = $this.parent(),
         // Filter empty input
         $inputs = $wrap.siblings().find('.customfile-filename')
           .filter(function(){ return !this.value }),
         $file = $('<input type="file" id="'+ uniqId +'" name="'+ $this.attr('name') +'"/>');
     // 1ms timeout so it runs after all other events
     // that modify the value have triggered
     setTimeout(function() {
       // Add a new input
       if ( $this.val() ) {
         // Check for empty fields to prevent
         // creating new inputs when changing files
         if ( !$inputs.length ) {
           $wrap.after( $file );
           $file.customFile();
         }
       // Remove and reorganize inputs
       } else {
         $inputs.parent().remove();
         // Move the input so it's always last on the list
         $wrap.appendTo( $wrap.parent() );
         $wrap.find('input').focus();
       }
     }, 1);
   });
 }
}( jQuery ));
$('input[type=file]').customFile();
</script>

(Luan Maik) #2

@ailimedavis
o elemento a ser estilizado é o <input type="text" class="customfile-filename">

o que o javascript faz é criar um campo de texto para colocar os nomes dos arquivos selecionados e um botão ao lado para invocar o input file, pois o input file está escondido.
Talvez você esteja adicionando o CSS no input file, e como ele está escondido, não muda nada
.


(Ailime Rodrigues) #3

mas não sei como adicionar o css no input text já que ele está no javascript e não manjo muito de js. poderia me dar uma dica?


(Luan Maik) #4

Posta seu codigo do Jquery validate que valida o input file para ver o que é possível ser feito.


(Luan Maik) #5

Na regra de validação do Jquery validate, tenta adicionar uma função como chamada do caso de validação:

rules: {

        meuInputFile: {
            required:{
                depends: function(){
                                $(".customfile-filename").css("border","2px red solid");
                         }
                    },
}

(Ailime Rodrigues) #6

Deu certo. Muito obrigada!!! :slight_smile:


(Luan Maik) #7

O único problema neste caso é que se tiver mais de 1 input file customizado pelo seu script n página, quando um for validado TODOS os inputs file ficarão com borda vermelha, pois todos terão a classe .customfile-filename, caso isso ocorrer você vai precisar especificar qual elemento de classe .customfile-filename deve ter a borda vermelha, especificando pelo index do elemento existentes em $(".customfile-filename")


(Ailime Rodrigues) #8

Sim. Percebi isso, tenho mais de um input file no formulario mas todos precisam ser validados. Então não vi problemas maiores.
Outra coisa que estou achando estranho é que as mensagens de erros dos inputs file ficam acima deles enquanto as dos outros campos ficam abaixo, como é realmente pra ser. Sem querer abusar mas sabes me dizer pq?

Obrigada.


(Luan Maik) #9

sobre os múltiplos input files na página, vc pode utilizar :
$("input[type='text'].customfile-filename:eq(0)") // Seleciona o primeiro
$("input[type='text'].customfile-filename:eq(1)") // Seleciona o segundo

Sobre a posição da mensagem de validação, preciso ver o código HTML/CSS com a mensagem já acionada.
Gera o problema, aperta F12 do navegador e na aba Elements copia o trecho do código.
Acredito que a mensagem esteja utilizando a posição do input file como referencia e não a do input text criado.


(Ailime Rodrigues) #10

Sim, está acontecendo isso mas não sei como reparar. :sweat:

<input type="file" name="plano_ensino" id="plano_ensino" class="customfile error" tabindex="-1" style="position: absolute; left: -9999px;">
<label for="plano_ensino" generated="true" class="error">Este campo é obrigatório.</label>
<input type="text" class="customfile-filename" style="border: 1px solid rgb(255, 35, 35);">
<button type="button" class="customfile-upload" tabindex="-1">Selecionar</button>

(Luan Maik) #11

No código que customiza (cria o input text e button) muda o:
$wrap.insertAfter( $file )
por
$wrap.insertBefore( $file )

a lógica é inserir o input text e button ANTES do input file.


(Ailime Rodrigues) #12

Já tinha tentado isso e não deu certo. Segue do mesmo jeito. input file, label, input text e button.


(Luan Maik) #13

coloca seu input file dentro de um span ou div e faz o seguinte.
troca:
$wrap.insertAfter( $file )
.append( $file, $input, ( isIE ? $label : $button ) );

por:

$wrap.insertAfter( $file ).parent()
       .prepend( $file, $input, ( isIE ? $label : $button ) );

(Ailime Rodrigues) #14

Segue a mesma coisa, com a diferença de que os inputs foram parar no topo da página.:expressionless:


(Luan Maik) #16

Desculpe. da pra corrigir com um passo simples.
No código de personalização original é só trocar a ordem de:

.append( $file, $input, ( isIE ? $label : $button ) );

por:

.append($input, ( isIE ? $label : $button ), $file );


(Ailime Rodrigues) #17

:grinning: :grinning: Po valeu! agora sim deu! Muito obrigada pela ajuda! :pray:🏻:pray:🏻:pray:🏻