为什么没有一个花哨的文件元素上传按钮推特引导?如果为上传按钮实现蓝色的主按钮,那就太好了。它甚至有可能巧妙的上传按钮使用CSS?(看起来像一个无法操纵的本机浏览器元素)


当前回答

基于绝对聪明的@claviska解决方案,所有的功劳都要归功于他。

全功能的Bootstrap 4文件输入验证和帮助文本。

基于输入组示例,我们有一个用于向用户显示文件名的虚拟输入文本字段,该字段由隐藏在标签按钮后面的实际输入文件字段上的onchange事件填充。除了包含引导验证支持外,我们还可以点击输入中的任何地方来打开文件对话框。

文件输入的三种状态

这三种可能的状态是未验证的、有效的和无效的,需要设置虚拟html输入标记属性。

Html标记作为输入

我们只引入了2个自定义类input-file-dummy和input-file-btn,以正确地设置样式并连接所需的行为。其他的都是标准的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>

JavaScript行为规定

虚拟输入需要是只读的,就像原来的例子一样,以防止用户更改只能通过打开文件对话框更改的输入。不幸的是,验证不会发生在只读字段上,所以我们切换了焦点和模糊(jquery事件onfocusin和onfocusout)输入的可编辑性,并确保它再次成为可验证的文件被选中。

除了使文本字段可单击之外,通过触发按钮的单击事件,填充虚拟字段的其余功能是由@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();
      });
  });
});

自定义样式调整

最重要的是,我们不希望只读字段在灰色背景和白色之间跳跃,所以我们确保它保持白色。span按钮没有指针光标,但我们需要为输入添加一个指针光标。

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

nJoy !

其他回答

我使用http://gregpike.net/demos/bootstrap-file-input/demo.html:

$('input[type=file]').bootstrapFileInput();

or

$('.file-inputs').bootstrapFileInput();

关于claviska的答案-如果你想在一个基本的文件上传中显示上传的文件名,你可以在输入的onchange事件中这样做。只需使用以下代码:

 <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>

这个jquery JS代码负责检索上传的文件名:

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

或者用香草JS:

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

这是Bootstrap 3,4,5的解决方案。

要制作一个看起来像按钮的功能文件输入控件,你只需要HTML:

HTML

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

这适用于所有现代浏览器,包括IE9+。如果你也需要对旧IE的支持,请使用下面所示的遗留方法。

这种技术依赖于HTML5的隐藏属性。Bootstrap 4使用以下CSS在不支持的浏览器中填充此特性。如果使用Bootstrap 3,则可能需要添加。

[hidden] {
  display: none !important;
}

旧IE的遗留方法

如果您需要IE8及以下版本的支持,请使用以下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;
}

注意,当你点击<label>时,旧的IE不会触发文件输入,所以CSS“膨胀”做了一些事情来解决这个问题:

使文件输入的跨度为周围<span>的全宽/高 使文件输入不可见


反馈和额外阅读

我已经发布了关于这个方法的更多细节,以及如何向用户显示选中了多少文件的示例:

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

多重上传解决方案

我调整了之前的两个答案,包括多次上传。这样,如果只选中一个文件,则标签显示文件名,反之则显示x个文件。

<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>

它也可以应用于更改按钮文本和类。

<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>

有可接受结果的简单解决办法:

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

以及风格:

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