We write the simplest and fastest input type file

Published on February 06, 2017

We write the simplest and fastest input type file

Good day, my dear friend. On the network, and on Habré, there are many articles on the topic of creating your input type = "file", but they all differ in a large number of crutches and a large amount of code, which, it seems to me, is not good. For, however paradoxical it may be, less is better .



A working example of what happens:



The principle of a customized input file itself does not have any special differences: we remove the input from the screen, and put everything on the shoulders of the label, to which we will add our own styles. The main difference is the small amount of code.

Let's start

We have input and label:

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

Now we remove the input from the screen by adding the following styles to the my class:

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

We also style the label itself by adding its own styles to it:

.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;
}

And now the fun part: javascript. Actually here it is:

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

It works as follows: When the user clicks on input with the .my class, then js starts tracking its change. Then if (if) comes into play. So if we have this (this) input is not empty (that is, the file was selected), then the element next to it (this is our label) will receive the text “Files selected” + number of files that the user selected . Well, if the user hasn’t selected anything, then the label will simply receive the text “Select files”.

Everything!

// Additional information

There may be a problem with the layout, which was also mine. And the problem may be with this notorious .prev (). In fact, there is a possibility that it is impossible to place the label and input file next to each other, and the text “Selected files” will be applied not to the label, but to the left element.

This problem can be solved like this:

Put the label and input in one div, and give this div a class, for example “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>

And replace in js

$(this).prev() 

on

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

Voila! Now, standing far apart, label and input are able to interact with each other.

It’s better, of course, to avoid such cases, but no one is protected from frameworks where you’re not writing inputs, but the framework itself generates them ...

Thank you for your attention.