ybiks
@ybiks
Студент

Можно ли добавлять свойства, значения в объект file?

Реализую плагин 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.
  • Вопрос задан
  • 224 просмотра
Решения вопроса 1
Stalker_RED
@Stalker_RED
Да, в input[type=file] можно добавить свои данные. Свойство dataset именно для таких случаев и существует.

var el = document.querySelector('input[type=file]');
el.dataset.mySuperPuperCustomData = 42;


Демо: https://jsfiddle.net/63x1jqq4/

P.S.
Ну и конечно-же вы можете повесить несколько обработчиков click на вашу кнопку. Но еще круче, повесить один на все кнопки!

$('#my_form').on('click', '.btn-image-delete', function(){
    /* эта ф-ция привязана не к куче ваших кнопок, а к форме.
        При клике на что-то, что находится внутри формы
        и имеет класс .btn-image-delete она выполнится
    */
     var btn = $(this)
     btn.closest('.img-block').remove()
})
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы