Skip to content

Instantly share code, notes, and snippets.

@b-aleksei
Last active October 1, 2021 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save b-aleksei/6656dce5c99344ecf74d3ded80275bc3 to your computer and use it in GitHub Desktop.
Save b-aleksei/6656dce5c99344ecf74d3ded80275bc3 to your computer and use it in GitHub Desktop.
(function() {
const fileLoaderContainers = document.querySelectorAll('.file-loader');
const renderFileLoader = function(fileLoaderContainer) {
const wrapper = fileLoaderContainer.querySelector('.file-loader__wrapper');
const btnAdd = fileLoaderContainer.querySelector('.js-fileloader-open');
if (!wrapper || !btnAdd) {
return;
}
const inputFileLoader = wrapper.querySelector('.file-loader__item');
const inputTemplate = inputFileLoader.cloneNode(true);
const maxLoaders = 10;
const limitBiteSize = 18000000;
const testImg = function(str) {
return /\.(png|jpe?g|pdf|doc|docx)$/i.test(str);
};
const setError = function(message) {
if (btnAdd) {
btnAdd.dataset.errorMess = message;
}
};
const isFileSizeCorrect = function(ctx) {
const inputs = ctx.querySelectorAll('.file-loader-js');
let size = 0;
inputs.forEach(function(i) {
if (i.files.length) {
size += i.files[0].size;
}
});
return size < limitBiteSize;
};
const renderNewInputAttr = function(attr) {
const inputs = wrapper.querySelectorAll('.file-loader-js');
const lastInput = inputs[inputs.length - 1];
const regExpNumber = /\d+/;
const regExpName = /\D+/;
const currentNumber = +lastInput[attr].match(regExpNumber)[0];
const currentName = lastInput[attr].match(regExpName)[0];
return currentName + (currentNumber + 1);
};
const addFileLoader = function() {
const id = renderNewInputAttr('id');
const name = renderNewInputAttr('name');
const loaderItem = inputTemplate.cloneNode(true);
const input = loaderItem.querySelector('input');
input.id = id;
input.name = name;
wrapper.append(loaderItem);
btnAdd.setAttribute('for', id );
};
const formatSize = function(number) {
let unitSize = ' Байт';
let divider = 1;
if (number > 1000000) {
unitSize = ' Мб';
divider = 1000000;
} else if (number > 1000) {
unitSize = ' Кб';
divider = 1000;
}
return (number / divider).toFixed(1) + unitSize;
};
wrapper.addEventListener('change', function(e) {
const target = e.target;
const parent = target.parentElement;
let errorMess = '';
if (!target.files.length) return;
if (!testImg(target.files[0].name)) {
target.value = '';
errorMess = 'Некорректный тип файла';
} else if (!isFileSizeCorrect(wrapper)) {
target.value = '';
errorMess = 'файлы превышают лимит 18мб';
} else {
if (wrapper.childElementCount < maxLoaders) {
const sizeEl = parent.querySelector('.file-loader__size');
const output = parent.querySelector('.file-loader__output');
if (sizeEl) {
sizeEl.innerText = formatSize(target.files[0].size);
}
if (output) {
output.innerText = target.files[0].name;
}
parent.classList.remove('unvisible');
addFileLoader();
}
}
target.setCustomValidity(errorMess);
setError(errorMess);
});
};
fileLoaderContainers.forEach(f => renderFileLoader(f));
})();
/*
<form class="file-loader support__form-item">
<i class="file-loader__note support__form-item">Вы можете прикрепить к обращению не более 10 файлов в формате .png, .jpeg, .pdf или .doc общим весом не более 18 мб</i>
<div class="file-loader__wrapper support__form-item">
<div class="file-loader__item support__form-item unvisible">
<input name="fileLoader1" id="fileLoader1" type="file" class="file-loader-js visually-hidden" accept=".png, .jpg, .jpeg, .pdf, .doc, .docx" aria-label="загрузить файл">
<div class="file-loader__view">
<output class="file-loader__output"></output>
<small class="file-loader__size"></small>
</div>
<button class="file-loader__remove" onclick="this.parentElement.remove()" type="button"></button>
</div>
</div>
<label for="fileLoader1" class="support__form-item js-fileloader-open file-loader__btn" data-error-mess="">Добавить ещё документ</label>
</form>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
border: 0;
clip: rect(0 0 0 0);
overflow: hidden;
}
.file-loader__wrapper {
display: flex;
flex-direction: column;
}
.file-loader__item {
position: relative;
display: flex;
padding: 10px 0;
align-items: center;
justify-content: space-between;
&:not(:first-child) {
border-top: 1px solid #C5C5C5;
}
}
.file-loader__btn {
position: relative;
align-items: center;
justify-content: center;
padding: 6px 16px 9px;
color: #0A5C6D;
cursor: pointer;
background: #eee
&::after {
position: absolute;
top: 100%;
left: 0;
content: attr(data-error-mess);
font-size: 12px;
color: #f32727;
background: none;
}
}
.file-loader__view {
display: flex;
flex-direction: column;
}
.file-loader__size {
font-size: 12px;
line-height: 15px;
color: #8F9BA3;
}
.file-loader__remove {
position: relative;
width: 40px;
height: 40px;
cursor: pointer;
background: none;
border: none;
&::before,
&::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 17px;
height: 2px;
background: #828E97;
}
&::before {
transform: translate(-50%, -50%) rotate(-45deg);
}
&::after {
transform: translate(-50%, -50%) rotate(45deg);
}
}
.unvisible {
visibility: hidden;
position: absolute;
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment