Пишемо самий простий і швидкий input type file

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



Робочий приклад того, що вийде:



Сам принцип кастомизированного 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.1 px;
height: 0.1 px;
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.18 s 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'и пишеш не ти, а їх генерує сам фреймворк…

Дякую за увагу.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.