Botão de upload do elemento de arquivo do formulário de inicialização do Twitter

573

Por que não existe um botão de upload de elemento de arquivo sofisticado para a inicialização do Twitter? Seria bom se o botão principal azul fosse implementado para o botão de upload. É ainda possível aperfeiçoar o botão de upload usando CSS? (parece um elemento nativo do navegador que não pode ser manipulado)

jkushner
fonte
13
Você pode encontrá-lo aqui. markusslima.github.io/bootstrap-filestyle
rh0dium

Respostas:

972

Aqui está uma solução para o Bootstrap 3 e 4.

Para criar um controle de entrada de arquivo funcional que se parece com um botão, você precisa apenas de HTML:

HTML

<label class="btn btn-default">
    Browse <input type="file" hidden>
</label>

Isso funciona em todos os navegadores modernos, incluindo o IE9 +. Se você também precisar de suporte para o IE antigo, use a abordagem herdada mostrada abaixo.

Esta técnica depende do hiddenatributo HTML5 . O Bootstrap 4 usa o seguinte CSS para ajustar esse recurso em navegadores não compatíveis. Pode ser necessário adicionar se você estiver usando o Bootstrap 3.

[hidden] {
  display: none !important;
}

Abordagem herdada para o IE antigo

Se você precisar de suporte para o IE8 e abaixo, use o seguinte HTML / CSS:

HTML

<span class="btn btn-default btn-file">
    Browse <input type="file">
</span>

CSS

.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: 100px;
    text-align: right;
    filter: alpha(opacity=0);
    opacity: 0;
    outline: none;
    background: white;
    cursor: inherit;
    display: block;
}

Observe que o IE antigo não aciona a entrada do arquivo quando você clica em um <label>, então o CSS "inchaço" faz algumas coisas para contornar isso:

  • Faz com que a entrada do arquivo abranja toda a largura / altura da área circundante <span>
  • Torna a entrada do arquivo invisível

Comentários e leituras adicionais

Publiquei mais detalhes sobre esse método, bem como exemplos de como mostrar ao usuário quais / quantos arquivos estão selecionados:

http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/

claviska
fonte
52
+ 1 Para mim, essa é de longe a melhor resposta. Solução muito concisa usando a versão mais recente do bootstrap.
Ulises
6
@Ulises @JaredEitnier @IvanWang Discordo respeitosamente. E ofereça um plug vergonhoso à minha resposta, que simplesmente usa o <label>elemento Como a melhor solução :)
Kirill Fuchs
9
Eu tenho que concordar com @KirillFuchs; etiqueta seria melhor. Plus - o usuário não pode ver se eles selecionaram o arquivo certo porque o botão não mostra o nome do arquivo selecionado: jsfiddle.net/36o9pdf9/1
danwild
1
O rótulo seria semanticamente melhor. Confira o artigo para um método de mostrar quais arquivos estão selecionados. (Alguns aplicativos auto-upload quando um arquivo é selecionado, também nesses casos o feedback filename não é crítica.)
claviska
1
Não consegui fazer isso funcionar no IE11 junto com um objeto FormData. De alguma forma, o IE está ignorando o campo de entrada quando está dentro de um elemento label e, como resultado, os dados do arquivo não estão disponíveis no objeto FormData.
René
385

Estou surpreso que não houve menção ao <label>elemento.

Solução:

<label class="btn btn-primary" for="my-file-selector">
    <input id="my-file-selector" type="file" class="d-none">
    Button Text Here
</label>

Não há necessidade de qualquer JS, ou CSS funky ...

Solução para incluir o nome do arquivo:

<label class="btn btn-primary" for="my-file-selector">
    <input id="my-file-selector" type="file" style="display:none" 
    onchange="$('#upload-file-info').html(this.files[0].name)">
    Button Text Here
</label>
<span class='label label-info' id="upload-file-info"></span>

A solução acima requer jQuery.

Kirill Fuchs
fonte
38
Essa resposta deve ser a aceita. É ainda melhor do que a resposta de @ claviska #
Fernando Carvalhosa
4
Não consigo entender por que essa não é a resposta aceita. Limpo, simples e estável (a menos que você está targetting <IE9, que é ...)
Jake Foster
3
Não consegui fazer isso funcionar no IE11 junto com um objeto FormData. De alguma forma, o IE está ignorando o campo de entrada quando está dentro de um elemento label e, como resultado, os dados do arquivo não estão disponíveis no objeto FormData.
René
25
bem, ele não exibe qual arquivo é escolhida (
godblessstrawberry
3
Você não precisa usar forse estiver agrupando o elemento de destino com o rótulo.
0xcaff
132

Sem nenhum plug-in adicional necessário, esta solução de inicialização funciona muito bem para mim:

<div style="position:relative;">
        <a class='btn btn-primary' href='javascript:;'>
            Choose File...
            <input type="file" style='position:absolute;z-index:2;top:0;left:0;filter: alpha(opacity=0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;background-color:transparent;color:transparent;' name="file_source" size="40"  onchange='$("#upload-file-info").html($(this).val());'>
        </a>
        &nbsp;
        <span class='label label-info' id="upload-file-info"></span>
</div>

demo:

http://jsfiddle.net/haisumbhatti/cAXFA/1/ (inicialização 2)

insira a descrição da imagem aqui

http://jsfiddle.net/haisumbhatti/y3xyU/ (inicialização 3)

insira a descrição da imagem aqui

codefreak
fonte
6
Eu tive alguns problemas com a área inferior do botão não clicável. Essa resposta me ajudou na inicialização 3: stackoverflow.com/a/18164555/44336
Paul Lemke
3
Esta é uma excelente solução, pois mostra o nome do arquivo anexado!
cb88
2
Alguém poderia explicar a necessidade do href = 'javascript :;' ? Eu não preciso do onchange = '$ ("# upload-file-info"). Html ($ (this) .val ());' para atualizar o elemento upload-file-info, mas a caixa de diálogo de upload de arquivo não será acionada sem o href.
user12121234
2
De onde vem o 'C: \ fakepath' e como me livrar dele?
Ya.
1
@Ya. C: \ fakepath é um recurso de segurança html5 e é prefixado para o caminho do arquivo se o manipularmos com javascript. Consulte esta postagem do blog davidwalsh.name/fakepath para obter detalhes.
Codefreak
88

Está incluído no garfo de inicialização de Jasny.

Um simples botão de upload pode ser criado usando

<span class="btn btn-file">Upload<input type="file" /></span>

Com o plugin fileupload, você pode criar widgets mais avançados. Dê uma olhada em http://jasny.github.io/bootstrap/javascript/#fileinput

Arnold Daniels
fonte
Isso funciona bem no IE9? Estou perguntando, porque suponho que a solução faça uso do Javascript e, ao mesmo tempo, "o IE não permite a manipulação do elemento de entrada type =” file ”do javascript por motivos de segurança".
Marek Příhoda 24/10/12
Sim, também funciona no IE9. Ele define a opacidade do elemento de entrada como 0, que felizmente funciona em todos os navegadores :). É explicado no artigo do modo quirks.
Arnold Daniels
1
ele não funciona com o jQuery 1.9.0, porque eles abandonaram o suporte a $ .browser
Giedrius
14
Parece terrível com o bootstrap regular - img688.imageshack.us/img688/948/pictureui.png
cwd
66

Os botões de upload são muito difíceis de estilizar, porque estilizam a entrada e não o botão.

mas você pode usar este truque:

http://www.quirksmode.org/dom/inputfile.html

Resumo:

  1. Pegue um normal <input type="file">e coloque-o em um elemento com position: relative.

  2. Para esse mesmo elemento pai, adicione uma imagem normal <input>e uma com os estilos corretos. Posicione esses elementos absolutamente, de modo que eles ocupem o mesmo lugar que o <input type="file">.

  3. Defina o índice z de <input type="file">como 2 para que fique na parte superior da entrada / imagem estilizada.

  4. Por fim, defina a opacidade <input type="file">como 0. O <input type="file">agora se torna efetivamente invisível e os estilos de entrada / imagem brilham, mas você ainda pode clicar no botão "Procurar". Se o botão estiver posicionado na parte superior da imagem, o usuário parece clicar na imagem e obter a janela de seleção de arquivo normal. (Observe que você não pode usar a visibilidade: oculto, porque um elemento verdadeiramente invisível também é clicável e precisamos permanecer clicáveis)

baptme
fonte
6
Isso é muito trabalho para estes dias. Usar algo pronto como a solução de Jasny na próxima resposta faz muito mais sentido.
mgPePe
2
Se o seu exemplo incluir suporte para o netscape, provavelmente não está atualizado.
Tifomismo
22

Funciona para mim:

Atualizar

Estilo de plugin jQuery :

// Based in: http://duckranger.com/2012/06/pretty-file-input-field-in-bootstrap/
// Version: 0.0.3
// Compatibility with: Bootstrap 3.2.0 and jQuery 2.1.1
// Use:
//     <input class="nice_file_field" type="file" data-label="Choose Document">
//     <script> $(".nice_file_field").niceFileField(); </script>
//
(function( $ ) {
  $.fn.niceFileField = function() {
    this.each(function(index, file_field) {
      file_field = $(file_field);
      var label = file_field.attr("data-label") || "Choose File";

      file_field.css({"display": "none"});

      nice_file_block_text  = '<div class="input-group nice_file_block">';
      nice_file_block_text += '  <input type="text" class="form-control">';
      nice_file_block_text += '  <span class="input-group-btn">';
      nice_file_block_text += '   <button class="btn btn-default nice_file_field_button" type="button">' + label + '</button>';
      nice_file_block_text += '  </span>';
      nice_file_block_text += '</div>';

      file_field.after(nice_file_block_text);

      var nice_file_field_button = file_field.parent().find(".nice_file_field_button");
      var nice_file_block_element = file_field.parent().find(".nice_file_block");

      nice_file_field_button.on("click", function(){ console.log("click"); file_field.click() } );
      file_field.change( function(){
        nice_file_block_element.find("input").val(file_field.val());
      });
    });
  };
})( jQuery );
fguillen
fonte
17

Resposta simplificada usando partes de outras respostas, principalmente user2309766 e dotcomsuperstar.

Recursos:

  • Usa o complemento do botão Bootstrap para o botão e o campo.
  • Apenas uma entrada; várias entradas seriam captadas por um formulário.
  • Nenhum css extra, exceto "display: none;" para ocultar a entrada do arquivo.
  • O botão visível aciona o evento de clique para entrada de arquivo oculto.
  • split para remover o caminho do arquivo, use regex e delimitadores '\' e '/'.

Código:

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="input-group">
  <span class="input-group-btn">
    <span class="btn btn-primary" onclick="$(this).parent().find('input[type=file]').click();">Browse</span>
    <input name="uploaded_file" onchange="$(this).parent().parent().find('.form-control').html($(this).val().split(/[\\|/]/).pop());" style="display: none;" type="file">
  </span>
  <span class="form-control"></span>
</div>

mindriot
fonte
12

Com alguma inspiração de outras postagens acima, aqui está uma solução completa que combina o que parece um campo de controle de formulário com um complemento de grupo de entrada para um widget de entrada de arquivo limpo que inclui um link para o arquivo atual.

.input-file { position: relative; margin: 60px 60px 0 } /* Remove margin, it is just for stackoverflow viewing */
.input-file .input-group-addon { border: 0px; padding: 0px; }
.input-file .input-group-addon .btn { border-radius: 0 4px 4px 0 }
.input-file .input-group-addon input { cursor: pointer; position:absolute; width: 72px; z-index:2;top:0;right:0;filter: alpha(opacity=0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0; background-color:transparent; color:transparent; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<div class="input-group input-file">
  <div class="form-control">
    <a href="/path/to/your/current_file_name.pdf" target="_blank">current_file_name.pdf</a>
  </div>
  <span class="input-group-addon">
    <a class='btn btn-primary' href='javascript:;'>
      Browse
      <input type="file" name="field_name" onchange="$(this).parent().parent().parent().find('.form-control').html($(this).val());">
    </a>
  </span>
</div>

dotcomly
fonte
9

Isso funciona perfeitamente para mim

<span>
    <input  type="file" 
            style="visibility:hidden; width: 1px;" 
            id='${multipartFilePath}' name='${multipartFilePath}'  
            onchange="$(this).parent().find('span').html($(this).val().replace('C:\\fakepath\\', ''))"  /> <!-- Chrome security returns 'C:\fakepath\'  -->
    <input class="btn btn-primary" type="button" value="Upload File.." onclick="$(this).parent().find('input[type=file]').click();"/> <!-- on button click fire the file click event -->
    &nbsp;
    <span  class="badge badge-important" ></span>
</span>
MoBKK
fonte
9

Confira a Entrada de arquivo do Twitter Bootstrap . Ele usa uma solução muito simples, basta adicionar um arquivo javascript e colar o seguinte código:

$('input[type=file]').bootstrapFileInput();
monsur.hoq
fonte
Link está quebrado (julho de 2019)
Yetti99 26/07/19
@ Yetti99 sim, está quebrado agora
monsur.hoq
@ Yetti99, mudei o link. Por favor, verifique agora.
monsur.hoq
6

Uma solução simples com resultado aceitável:

<input type="file" class="form-control">

E o estilo:

input[type=file].form-control {
    height: auto;
}
Salar
fonte
5

Solução para upload múltiplo

Ajustei duas respostas anteriores para incluir vários uploads. Dessa forma, o rótulo mostra o nome do arquivo, se apenas um estiver selecionado, ou x filesno caso oposto.

<label class="btn btn-primary" for="my-file-selector">
    <input id="my-file-selector" type="file" multiple="multiple" style="display:none"
        onchange="$('#upload-file-info').html(
            (this.files.length > 1) ? this.files.length + ' files' : this.files[0].name)">                     
    Files&hellip;
</label>
<span class='label label-info' id="upload-file-info"></span>

insira a descrição da imagem aqui

Também pode ser aplicado para alterar o texto e a classe do botão.

<label class="btn btn-primary" for="multfile">
    <input id="multfile" type="file" multiple="multiple" style="display:none"
        onchange="$('#multfile-label').html(
            (this.files.length == 1) ? this.files[0].name : this.files.length + ' files');
            $(this).parent().addClass('btn-success')">
    <span id="multfile-label">Files&hellip;</span>
</label>

insira a descrição da imagem aqui

Nuno André
fonte
4

Criei um botão de upload personalizado para aceitar apenas imagens, que podem ser modificadas conforme sua exigência.

Espero que isto ajude!! :)

(Estrutura usada do Bootstrap)

Codepen-link

HTML

<center>
 <br />
 <br />
 <span class="head">Upload Button Re-Imagined</span>
 <br />
 <br />
 <div class="fileUpload blue-btn btn width100">
   <span>Upload your Organizations logo</span>
   <input type="file" class="uploadlogo" />
 </div>
</center>

CSS

 .head {
   font-size: 25px;
   font-weight: 200;
 }

 .blue-btn:hover,
 .blue-btn:active,
 .blue-btn:focus,
 .blue-btn {
   background: transparent;
   border: solid 1px #27a9e0;
   border-radius: 3px;
   color: #27a9e0;
   font-size: 16px;
   margin-bottom: 20px;
   outline: none !important;
   padding: 10px 20px;
 }

 .fileUpload {
   position: relative;
   overflow: hidden;
   height: 43px;
   margin-top: 0;
 }

 .fileUpload input.uploadlogo {
   position: absolute;
   top: 0;
   right: 0;
   margin: 0;
   padding: 0;
   font-size: 20px;
   cursor: pointer;
   opacity: 0;
   filter: alpha(opacity=0);
   width: 100%;
   height: 42px;
 }


 /*Chrome fix*/

 input::-webkit-file-upload-button {
   cursor: pointer !important;
 }

JS

// You can modify the upload files to pdf's, docs etc
//Currently it will upload only images
$(document).ready(function($) {

  // Upload btn
  $(".uploadlogo").change(function() {
    readURL(this);
  });

  function readURL(input) {
    var url = input.value;
    var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase();
    if (input.files && input.files[0] && (ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "gif" || ext == "svg")) {
      var path = $('.uploadlogo').val();
      var filename = path.replace(/^.*\\/, "");
      $('.fileUpload span').html('Uploaded logo : ' + filename);
      // console.log(filename);
    } else {
      $(".uploadlogo").val("");
      $('.fileUpload span').html('Only Images Are Allowed!');
    }
  }
});
Ashwin
fonte
4

este é o melhor estilo de upload de arquivo que eu gosto:

<div class="fileupload fileupload-new" data-provides="fileupload">
  <div class="input-append">
    <div class="uneditable-input span3"><i class="icon-file fileupload-exists"></i> <span class="fileupload-preview"></span></div><span class="btn btn-file"><span class="fileupload-new">Select file</span><span class="fileupload-exists">Change</span><input type="file" /></span><a href="#" class="btn fileupload-exists" data-dismiss="fileupload">Remove</a>
  </div>
</div>

você pode obter demo e mais estilos em:

http://www.jasny.net/bootstrap/javascript/#fileinput

mas usando isso, você deve substituir a inicialização do twitter por arquivos de inicialização jasny.

Saudações.

marinha
fonte
4

Baseado na solução absolutamente brilhante @claviska, a quem todo o crédito é devido.

Entrada de arquivo Bootstrap 4 com todos os recursos com validação e texto de ajuda.

Com base no exemplo do grupo de entrada , temos um campo de texto de entrada fictício usado para exibir o nome do arquivo para o usuário, que é preenchido a partir do onchangeevento no campo real do arquivo de entrada escondido atrás do botão de rótulo. Além de incluir o suporte à validação do bootstrap 4 , também foi possível clicar em qualquer lugar da entrada para abrir a caixa de diálogo do arquivo.

Três estados da entrada do arquivo

Os três estados possíveis são não validados, válidos e inválidos com o requiredconjunto de atributos da marca de entrada html dummy .

insira a descrição da imagem aqui

Marcação HTML para a entrada

Introduzimos apenas duas classes personalizadas input-file-dummye input-file-btnmodelamos e conectamos adequadamente o comportamento desejado. Tudo o resto é a marcação padrão do Bootstrap 4.

<div class="input-group">
  <input type="text" class="form-control input-file-dummy" placeholder="Choose file" aria-describedby="fileHelp" required>
  <div class="valid-feedback order-last">File is valid</div>
  <div class="invalid-feedback order-last">File is required</div>
  <label class="input-group-append mb-0">
    <span class="btn btn-primary input-file-btn">
      Browse… <input type="file" hidden>
    </span>
  </label>
</div>
<small id="fileHelp" class="form-text text-muted">Choose any file you like</small>

Disposições comportamentais JavaScript

A entrada fictícia precisa ser apenas de leitura, conforme o exemplo original, para impedir que o usuário altere a entrada que só pode ser alterada através da caixa de diálogo de arquivo aberto. Infelizmente, a validação não ocorre nos readonlycampos, portanto, alternamos a editabilidade da entrada em foco e desfoque ( eventos jquery onfocusin e onfocusout) e garantimos que ela se torne validável novamente quando um arquivo for selecionado.

Além de tornar o campo de texto clicável, acionando o evento de clique do botão, o restante da funcionalidade de preenchimento do campo fictício foi visualizado por @claviska.

$(function () {
  $('.input-file-dummy').each(function () {
    $($(this).parent().find('.input-file-btn input')).on('change', {dummy: this}, function(ev) {
      $(ev.data.dummy)
        .val($(this).val().replace(/\\/g, '/').replace(/.*\//, ''))
        .trigger('focusout');
    });
    $(this).on('focusin', function () {
        $(this).attr('readonly', '');
      }).on('focusout', function () {
        $(this).removeAttr('readonly');
      }).on('click', function () {
        $(this).parent().find('.input-file-btn').click();
      });
  });
});

Ajustes de estilo personalizado

Mais importante ainda, não queremos que o readonlycampo pule entre fundo cinza e branco, para garantir que ele permaneça branco. O botão span não possui um cursor de ponteiro, mas precisamos adicionar um para a entrada de qualquer maneira.

.input-file-dummy, .input-file-btn {
  cursor: pointer;
}
.input-file-dummy[readonly] {
  background-color: white;
}

nJoy!

nickl-
fonte
2

/ * * Bootstrap 3 filestyle * http://dev.tudosobreweb.com.br/bootstrap-filestyle/ * * Copyright (c) 2013 Markus Vinicius da Silva Lima * Atualize o bootstrap 3 de Paulo Henrique Foxer * Versão 2.0.0 * Licenciado sob a licença do MIT. * * /

(function ($) {
"use strict";

var Filestyle = function (element, options) {
    this.options = options;
    this.$elementFilestyle = [];
    this.$element = $(element);
};

Filestyle.prototype = {
    clear: function () {
        this.$element.val('');
        this.$elementFilestyle.find(':text').val('');
    },

    destroy: function () {
        this.$element
            .removeAttr('style')
            .removeData('filestyle')
            .val('');
        this.$elementFilestyle.remove();
    },

    icon: function (value) {
        if (value === true) {
            if (!this.options.icon) {
                this.options.icon = true;
                this.$elementFilestyle.find('label').prepend(this.htmlIcon());
            }
        } else if (value === false) {
            if (this.options.icon) {
                this.options.icon = false;
                this.$elementFilestyle.find('i').remove();
            }
        } else {
            return this.options.icon;
        }
    },

    input: function (value) {
        if (value === true) {
            if (!this.options.input) {
                this.options.input = true;
                this.$elementFilestyle.prepend(this.htmlInput());

                var content = '',
                    files = [];
                if (this.$element[0].files === undefined) {
                    files[0] = {'name': this.$element[0].value};
                } else {
                    files = this.$element[0].files;
                }

                for (var i = 0; i < files.length; i++) {
                    content += files[i].name.split("\\").pop() + ', ';
                }
                if (content !== '') {
                    this.$elementFilestyle.find(':text').val(content.replace(/\, $/g, ''));
                }
            }
        } else if (value === false) {
            if (this.options.input) {
                this.options.input = false;
                this.$elementFilestyle.find(':text').remove();
            }
        } else {
            return this.options.input;
        }
    },

    buttonText: function (value) {
        if (value !== undefined) {
            this.options.buttonText = value;
            this.$elementFilestyle.find('label span').html(this.options.buttonText);
        } else {
            return this.options.buttonText;
        }
    },

    classButton: function (value) {
        if (value !== undefined) {
            this.options.classButton = value;
            this.$elementFilestyle.find('label').attr({'class': this.options.classButton});
            if (this.options.classButton.search(/btn-inverse|btn-primary|btn-danger|btn-warning|btn-success/i) !== -1) {
                this.$elementFilestyle.find('label i').addClass('icon-white');
            } else {
                this.$elementFilestyle.find('label i').removeClass('icon-white');
            }
        } else {
            return this.options.classButton;
        }
    },

    classIcon: function (value) {
        if (value !== undefined) {
            this.options.classIcon = value;
            if (this.options.classButton.search(/btn-inverse|btn-primary|btn-danger|btn-warning|btn-success/i) !== -1) {
                this.$elementFilestyle.find('label').find('i').attr({'class': 'icon-white '+this.options.classIcon});
            } else {
                this.$elementFilestyle.find('label').find('i').attr({'class': this.options.classIcon});
            }
        } else {
            return this.options.classIcon;
        }
    },

    classInput: function (value) {
        if (value !== undefined) {
            this.options.classInput = value;
            this.$elementFilestyle.find(':text').addClass(this.options.classInput);
        } else {
            return this.options.classInput;
        }
    },

    htmlIcon: function () {
        if (this.options.icon) {
            var colorIcon = '';
            if (this.options.classButton.search(/btn-inverse|btn-primary|btn-danger|btn-warning|btn-success/i) !== -1) {
                colorIcon = ' icon-white ';
            }

            return '<i class="'+colorIcon+this.options.classIcon+'"></i> ';
        } else {
            return '';
        }
    },

    htmlInput: function () {
        if (this.options.input) {
            return '<input type="text" class="'+this.options.classInput+'" style="width: '+this.options.inputWidthPorcent+'% !important;display: inline !important;" disabled> ';
        } else {
            return '';
        }
    },

    constructor: function () {
        var _self = this,
            html = '',
            id = this.$element.attr('id'),
            files = [];

        if (id === '' || !id) {
            id = 'filestyle-'+$('.bootstrap-filestyle').length;
            this.$element.attr({'id': id});
        }

        html = this.htmlInput()+
             '<label for="'+id+'" class="'+this.options.classButton+'">'+
                this.htmlIcon()+
                '<span>'+this.options.buttonText+'</span>'+
             '</label>';

        this.$elementFilestyle = $('<div class="bootstrap-filestyle" style="display: inline;">'+html+'</div>');

        var $label = this.$elementFilestyle.find('label');
        var $labelFocusableContainer = $label.parent();

        $labelFocusableContainer
            .attr('tabindex', "0")
            .keypress(function(e) {
                if (e.keyCode === 13 || e.charCode === 32) {
                    $label.click();
                }
            });

        // hidding input file and add filestyle
        this.$element
            .css({'position':'absolute','left':'-9999px'})
            .attr('tabindex', "-1")
            .after(this.$elementFilestyle);

        // Getting input file value
        this.$element.change(function () {
            var content = '';
            if (this.files === undefined) {
                files[0] = {'name': this.value};
            } else {
                files = this.files;
            }

            for (var i = 0; i < files.length; i++) {
                content += files[i].name.split("\\").pop() + ', ';
            }

            if (content !== '') {
                _self.$elementFilestyle.find(':text').val(content.replace(/\, $/g, ''));
            }
        });

        // Check if browser is Firefox
        if (window.navigator.userAgent.search(/firefox/i) > -1) {
            // Simulating choose file for firefox
            this.$elementFilestyle.find('label').click(function () {
                _self.$element.click();
                return false;
            });
        }
    }
};

var old = $.fn.filestyle;

$.fn.filestyle = function (option, value) {
    var get = '',
        element = this.each(function () {
            if ($(this).attr('type') === 'file') {
                var $this = $(this),
                    data = $this.data('filestyle'),
                    options = $.extend({}, $.fn.filestyle.defaults, option, typeof option === 'object' && option);

                if (!data) {
                    $this.data('filestyle', (data = new Filestyle(this, options)));
                    data.constructor();
                }

                if (typeof option === 'string') {
                    get = data[option](value);
                }
            }
        });

    if (typeof get !== undefined) {
        return get;
    } else {
        return element;
    }
};

$.fn.filestyle.defaults = {
    'buttonText': 'Escolher arquivo',
    'input': true,
    'icon': true,
    'inputWidthPorcent': 65,
    'classButton': 'btn btn-primary',
    'classInput': 'form-control file-input-button',
    'classIcon': 'icon-folder-open'
};

$.fn.filestyle.noConflict = function () {
    $.fn.filestyle = old;
    return this;
};

// Data attributes register
$('.filestyle').each(function () {
    var $this = $(this),
        options = {
            'buttonText': $this.attr('data-buttonText'),
            'input': $this.attr('data-input') === 'false' ? false : true,
            'icon': $this.attr('data-icon') === 'false' ? false : true,
            'classButton': $this.attr('data-classButton'),
            'classInput': $this.attr('data-classInput'),
            'classIcon': $this.attr('data-classIcon')
        };

    $this.filestyle(options);
});
})(window.jQuery);
Paulo Henrique Foxer
fonte
2

Modifiquei a resposta @claviska e funciona como eu gosto (Bootstrap 3, 4 não testado):

<label class="btn btn-default">
    <span>Browse</span>
    <input type="file" style="display: none;" onchange="$(this).prev('span').text($(this).val()!=''?$(this).val():'Browse')">
</label>
marioosh
fonte
2

insira a descrição da imagem aqui

O código a seguir faz como acima da imagem

Html

<form>
<div class="row">
<div class="col-lg-6">
<label for="file">
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Browse</button>
</span>
<input type="text" class="form-control" id="info" readonly="" style="background: #fff;" placeholder="Search for...">
</div><!-- /input-group -->
</label>
</div><!-- /.col-lg-6 -->
</div>

</div>
<input type="file" style="display: none;" onchange="$('#info').val($(this).val().split(/[\\|/]/).pop()); " name="file" id="file">
</form>

Javascript

<script type="text/javascript">

$(function() {
    $("label[for=file]").click(function(event) {
        event.preventDefault();
        $("#file").click();
    });
});

</script>
NaveenDA
fonte
1

Eu tenho o mesmo problema e tento assim.

<div>
<button type='button' class='btn btn-info btn-file'>Browse</button>
<input type='file' name='image'/>
</div>

O CSS

<style>
.btn-file {
    position:absolute;
}
</style>

O JS

<script>
$(document).ready(function(){
    $('.btn-file').click(function(){
        $('input[name="image"]').click();
    });
});
</script>

Nota: O botão .btn-file deve estar na mesma tag que o arquivo de entrada

Espero que você tenha encontrado a melhor solução ...

Esgi Dendyanri
fonte
1

Tente seguir no Bootstrap v.3.3.4

<div>
    <input id="uplFile" type="file" style="display: none;">

    <div class="input-group" style="width: 300px;">
        <div  id="btnBrowse"  class="btn btn-default input-group-addon">Select a file...</div>
        <span id="photoCover" class="form-control">
    </div>
</div>

<script type="text/javascript">
    $('#uplFile').change(function() {
        $('#photoCover').text($(this).val());
    });

    $('#btnBrowse').click(function(){
        $('#uplFile').click();
    });
</script>
Siyavash Hamdi
fonte
1

Aqui está um truque alternativo, não é a melhor solução, mas apenas oferece uma escolha

Código HTML:

<button clss="btn btn-primary" id="btn_upload">Choose File</button>
<input id="fileupload" class="hide" type="file" name="files[]">

Javascript:

$("#btn_upload").click(function(e){
e.preventDefault();
$("#fileupload").trigger('click');
});
Somwang Souksavatd
fonte
1

Em relação à resposta claviska - se você quiser mostrar o nome do arquivo carregado em um upload básico de arquivo, você pode fazê-lo no onchangeevento de entradas . Basta usar este código:

 <label class="btn btn-default">
                    Browse...
                    <span id="uploaded-file-name" style="font-style: italic"></span>
                    <input id="file-upload" type="file" name="file"
                           onchange="$('#uploaded-file-name').text($('#file-upload')[0].value);" hidden>
 </label>

Esse código jquery JS é responsável pela recuperação do nome do arquivo carregado:

$('#file-upload')[0].value

Ou com baunilha JS:

document.getElementById("file-upload").value

exemplo

Michał Stochmal
fonte
1

Eu pensei em adicionar meu valor de três centavos, apenas para dizer como os arquivos padrão .custom-file-labele custom-file-inputBS4 são inseridos e como isso pode ser usado.

A última classe está no grupo de entrada e não é visível. Enquanto o primeiro é o rótulo visível e possui um pseudoelemento: after que se parece com um botão.

<div class="custom-file">
<input type="file" class="custom-file-input" id="upload">
<label class="custom-file-label" for="upload">Choose file</label>
</div>

Você não pode adicionar classes aos elementos psuedo, mas pode estilizá-las em CSS (ou SASS).

.custom-file-label:after {
    color: #fff;
    background-color: #1e7e34;
    border-color: #1c7430;
    pointer: cursor;
}
Matteo Ferla
fonte
0

Não é necessário um truque sofisticado:

HTML:

<form method="post" action="/api/admin/image" enctype="multipart/form-data">
    <input type="hidden" name="url" value="<%= boxes[i].url %>" />
    <input class="image-file-chosen" type="text" />
    <br />
    <input class="btn image-file-button" value="Choose Image" />
    <input class="image-file hide" type="file" name="image"/> <!-- Hidden -->
    <br />
    <br />
    <input class="btn" type="submit" name="image" value="Upload" />
    <br />
</form>

JS:

$('.image-file-button').each(function() {
      $(this).off('click').on('click', function() {
           $(this).siblings('.image-file').trigger('click');
      });
});
$('.image-file').each(function() {
      $(this).change(function () {
           $(this).siblings('.image-file-chosen').val(this.files[0].name);
      });
});

CUIDADO: Os três elementos do formulário em questão DEVEM ser irmãos um do outro (arquivo de imagem escolhido, botão de arquivo de imagem, arquivo de imagem)

mattdlockyer
fonte