Реализую плагин Jquery, для предварительного показа изображений перед их отправкой на сервер. Решив добавить возможность удаления изображений прям на странице, возник вопрос эстетического характера. Будет ли считаться хорошим тоном, хранение сгенерированного id для изображения прям в его объекте.
<input type="file" multiple name="photo[]" eI-list="photo">
<ul eI-listShow="photo"></ul>
//Код урезанный, и не проверялся на работоспособность в таком виде
;(function($){
var eiSettings = {
prefix: 'eI',
optionsFiles: {
/*Маска элементов рендера изображения документа*/
maskList: `<li {{id}}>
<span>Наименование: {{name}}</span><br>
<span>Размер: {{size}}</span><br>
<span>Формат: {{format}}</span><hr>
<img src="{{src}}">
<button class="{{delete}}" type="button">Удалить</button>
</li>`,
/*Функция получающая количество бит файла, возвращающая корректный вес*/
getSize: function(number){
var kb = ( number / 1024 ).toFixed( 1 );
return ( kb > 1024 ) ? kb.toFixed( 1 ) + 'Мбайт' : kb + 'Кбайт';
}
}
}
$.fn.eI = function(method){
/*Универсальная функция изменения маски на значение*/
function replaceSintax(string, data){
return String(string).replace(/\{\{(\w*)\}\}/g, ( match, value ) => {
return String( data[ value ] );
});
}
var methods = {
showFiles: function(options){
if(typeof options != 'object'){
//Если объект опций не пришел или не объект, то записываем стандартные настройки
options = eiSettings.optionsFiles;
}else{
//Если пришел то прототипируем от стандартных настроек
options.__proto__ = eiSettings.optionsFiles;
}
/*Перебираем все вошедшие input'ы с типом file*/
this.each(function(){
var $this = $(this),
list = options.list || paramsAttr( $( this ).attr( eiSettings.prefix + '-list' )),
listObj = $('['+eiSettings.prefix+'-listShow="'+list+'"]');
/*Вешаем событие клика на все элементы имеющие класс удаления файла*/
listObj.on('click', '.deleteFile', function(e){
/*Здесь должна быть логика удаления файла из DOM и из массива файлов*/
})
function paramsAttr(s){
return s ? s.replace(/\s?/g, '').split(',') : false;
}
//Получаем формат(image/png, image/jpeg...)
function getFormat(s){
return s.split('/')[1];
}
//Создание id
function getId(){
return Math.random().toString(36).slice(2);
}
$this.on('change', function(){
var files = this.files;
listObj.empty();
$.each(files, function(i){
var file = this;
if(!file.type.match('image.*')) return true;//Если не изображение то игнорируем
var show = new FileReader();
show.onload = (function(e){
return function(e){
//Объект данных для DOM
var data = {
name: file.name,
src: e.target.result,
delete: ' deleteFile ',
format: getFormat(file.type),
size: options.getSize(file.size),
count: (eiSettings.prefix + '-idFile="'+ i +'"')
}
//Заменяем маски на данные и рендерим в DOM
listObj.append( replaceSintax( options.maskList, data ) )
}
})(file)
//Вызов события
show.readAsDataURL(file)
})
})
})
}
}
//Код не мой, брал из статьи по написанию плагинов для Jquery
if(methods[method]){
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
}else if(typeof method === 'object' || ! method){
return methods.init.apply( this, arguments );
}else{
$.error( 'Method ' + method + ' not found. eI plagin Error!' );
}
}
})(jQuery)
$('input[type="file"]').eI('showFiles');
$('input[type="file"]').change();//Для мозилы, так как там после перезагрузки страницы файлы остаются в объекте, вот мы их и рендерим
P.S. id мне нужен для того чтобы понимать какая картинка из DOM относится к объекту файла. Конечно же я мог в момент рендера изображения, вешать click на кнопку удаления, и сразу передавать туда объект. НО! Это `невозможно` сделать так как я добавил возможность использовать маску, и передаю её в append.