Пишем самый простой и быстрый input type file

в 10:53, , рубрики: css, html, input, input file, input[type=file], jquery, jqyery, Веб-разработка, загрузка файлов, метки:

Доброго времени суток, мой дорогой друг. В сети, да и на Хабре, есть множество статей на тему создания своего input type=«file», но все они отличаются большим количеством костылей и большим количеством кода, что, как мне кажется, не есть хорошо. Ибо, как бы это не было парадоксально, меньше — лучше.

Пишем самый простой и быстрый input type file - 1

Рабочий пример того, что получится:

Сам принцип кастомизированного input file особых отличий не имеет: убираем с экрана input, и всё возлагаем на плечи label, которому мы добавим свои стили. Главное отличие — малое кол-во кода.

Начнём

Мы имеем input и label

<label for="myfile" class="label">Выберите файлы</label>
<input type="file" class="my" id="myfile" name="myfile" multiple>

Теперь уберём с экрана input, добавив классу my следующие стили:

.my {
  width: 0.1px;
  height: 0.1px;
  opacity: 0;
  overflow: hidden;
  position: absolute;
  z-index: -1;
}

А также стилизуем сам label, добавив ему свои стили:

.label {
    width: 180px;
    height: 50px;
    border-radius: 4px;
    text-align: center;
    cursor: pointer;
    display: block;
    font: 14px/50px Tahoma;
    transition: all 0.18s ease-in-out;
    border: 1px solid #333;
    color: #333;
}

.label:hover {
    color: white;
    background: #333;
}

И теперь самое интересное: javascript. Собственно вот он:

$('.my').change(function() {
    if ($(this).val() != '') $(this).prev().text('Выбрано файлов: ' + $(this)[0].files.length);
    else $(this).prev().text('Выберите файлы');
});

Он работает следующим образом: Когда пользователь жмёт на input с классом .my, то js начинает отслеживать его изменение. Дальше в дело вступает if (если). Так вот если у нас этот (this) input не пустой (то есть файл был какой-то выбран), то стоящий по соседству выше элемент (это у нас label) получит текст «Выбрано файлов» + кол-во файлов, которое выбрал пользователь. Ну а если пользователь ничего не выбрал, то label просто получит текст «Выберите файлы».

Всё!

// Дополнительная информация

Может возникнуть проблема с вёрсткой, какая была и у меня. А проблема может заключаться с этим пресловутым .prev(). По факту, есть вероятность того, что невозможно расположить label и input file рядом друг с другом, и текст «Выбрано файлов» будет применяется не к label, а к левому элементу.

Эту проблему можно решить вот так:

Поместите label и input в один div, и дайте этому div'у класс, к примеру «box-form»

<div class="box-form">
<p>Текст какой-то</p>
<div>
<label for="myfile" class="label">Выберите файлы</label>
</div>
<div>
<div></div>
<input type="file" class="my" id="myfile" name="myfile" multiple>
</div>
</div>

И замените в js

$(this).prev() 

на

$(this).closest('.box-form').children('.label')

Вуаля! Теперь, стоявшие далеко друг от друга, label и input способны взаимодействовать друг с другом.

Лучше, конечно, избегать таких случаев, но никто не защищён от фреймворков, где input'ы пишешь не ты, а их генерирует сам фреймворк…

Спасибо за внимание

Автор: kirigosh

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js