<div id="file-uploader1" class="wrapper js"></div>

<div id="file-uploader2" class="wrapper js"></div>

<script type="text/template" id="file-uploader-template">
	<form class="js--upload-form is-droppable">
		<span class="text--center">
			<i class="fa fa-cloud-upload fa-2"></i>
			<span class="js--advanced-upload">Drop files to attach, or <label class="btn btn--link" for="file">browse</label></span>
			<input type="file" name="files[]" id="file" class="js--basic-upload hide" data-multiple-caption="{count} files selected" multiple="" accept=".pdf,.xlsx">
		</span>
		<table class="js--files-list" border="0"></table>
	</form>
</script>

<script type="text/template" id="document-item-view">
<td><a href="<%= data %>" download="<%= name %>" target="_blank"><%= name %></a></td>
<td><%= type %>
<td><button class="btn btn--link js--remove-file"><i class="fa fa-times-circle"></i></button></td>
</script>
.wrapper {
	margin: 20px;
}

.hide {
	display: none;
}

.text--center {
	display: block;
	text-align: center;
}

.is-droppable {
	border: 1px dashed #ccc;
	// border-radius: 10px;
	padding: 20px;
	margin: 20px 0;
	&.is-dragover {
		// color: #fff;
		border-color: #999;
		background-color: #e2e2e2;
	}
}
.btn--link {
	color: #0079c1;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
}
.js .box__file {
	display: none;
}
View Compiled
var isAdvancedUpload = function() {
  var div = document.createElement('div');
  return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && 'FormData' in window && 'FileReader' in window;
}();

var tests = {
	filereader	: typeof FileReader != 'undefined',
	dnd			: 'draggable' in document.createElement('span'),
	formdata	: !!window.FormData,
	progress	: "upload" in new XMLHttpRequest
};

var supports = {
	FileReader	: 'FileReader' in window // typeof FileReader != 'undefined'
};

// var support = {
// 	filereader	: document.getElementById('filereader'),
// 	formdata	: document.getElementById('formdata'),
// 	progress	: document.getElementById('progress')
// };
var acceptedTypes = {
	'application/pdf'	: true,
	'image/png'			: true,
	'image/jpeg'		: true,
	'image/gif'			: true
};

const acceptedMimeTypes = {
	'.pdf'	: 'application/pdf',
	'.doc'	: 'application/msword',
	'.docx'	: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
	'.rtf'	: 'text/rtf',
	'.xls'	: '',
	'.xlsx'	: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
	'.csv'	: 'text/csv',
	'.jpg'	: 'image/jpeg',
	'.jpeg'	: 'image/jpeg',
	'.txt'	: 'text/plain'
};

var FileModel = Backbone.Model.extend({
	defaults: {
		name				: null,
		type				: null,
		size				: null,
		data				: null,
		lastModified		: null,
		lastModifiedDate	: null
	}
});

var FilesCollection = Backbone.Collection.extend({
	model	: FileModel,
	url		: null
});

var FileView = Marionette.ItemView.extend({
	tagName		: 'tr',
	model		: FileModel,
	// template	: _.template('<a href="<%= data %>" download="<%= name %>" target="_blank"><%= name %></a>'),
	// template	: _.template('<a href="<%= data %>" download="<%= name %>" target="_blank"><%= name %></a> <button class="btn btn--link js--remove-file"><i class="fa fa-times-circle"></i></button>'),
	template	: '#document-item-view',
	
	ui: {
		btnRemoveFile: '.js--remove-file'
	},
	
	events: {
		'click @ui.btnRemoveFile': 'btnRemoveFileClicked'
	},
	
	initialize: function() {
		console.log("FileView :: initialize", this.options);
	},
	
	onRender: function() {
		console.log("FileView :: onRender", this.model.toJSON());
	},
	
	btnRemoveFileClicked: function() {
		this.triggerMethod("remove:file", this.model);
	}
										  
});

var FilesListView = Marionette.CompositeView.extend({
	
	// tagName				: 'ul',
	// template			: '.js--upload-form',
	childViewContainer	: '.js--files-list',
	childView			: FileView,
	collection			: FilesCollection,
	
// 	template: _.template(''),
		
// });

// var FileUploaderView = Marionette.LayoutView.extend({
	
	template: '#file-uploader-template',
	// regions: {
	// 	fileUploader: '.js--uploaded-files'
	// },
	
	onRender: function() {
		// var fileUploader = new FilesListView({collection: new FilesCollection()});
		// this.showChildView('fileUploader', fileUploader);
	},
	
	ui: {
		basicUpload		: '.js--basic-upload',
		advancedUpload	: '.js--advanced-upload',
		form			: '.js--upload-form',
		fileInput		: 'input[type="file"]'
	},
	
	events: {
		'change @ui.fileInput'	: 'onFilesSelected',
		// 'drop @ui.form' : 'onFilesDropped'
	},
	
	// modelEvents: {
	// 	'change:data': 'reRenderCollection'
	// },
	
	// collectionEvents: {
	// 	add: 'onRenderCollection'
	// },
	
	initialize: function() {
		console.log("FilesListView :: initialize", this.options);
	},
	
	onChildviewRemoveFile: function(cv, model) {
		console.log("FilesListView :: onChildviewRemoveFile", cv, model);
		this.collection.remove(model);
	},
	
	onRender: function() {
		console.log("FilesListView :: onRender", this.collection.toJSON());
		
		if (isAdvancedUpload) {
			
			this.ui.advancedUpload.removeClass('hide');
			this.ui.basicUpload.addClass('hide');
			
			var $form = this.ui.form;
			$form
				.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
					e.preventDefault();
					e.stopPropagation();
				})
				.on('dragover dragenter', function() {
					$form.addClass('is-dragover');
				})
				.on('dragleave dragend drop', function() {
					$form.removeClass('is-dragover');
				});
		
			$form.on('drop', this.onFilesDropped.bind(this));
			
		} else {
			
			this.ui.advancedUpload.addClass('hide');
			this.ui.basicUpload.removeClass('hide');

		}
	},
	
// 	reRenderCollection: function() {
// 		console.log("FilesListView :: reRenderCollection", this.collection.toJSON());
// 		this.triggerMethod("render:collection");
// 	},
	
// 	onRenderCollection: function() {
// 		console.log("FilesListView :: onRenderCollection", this.collection.toJSON());
// 	},

	onFilesSelected: function(e) {
		console.debug("onFilesSelected", e);
		this.triggerMethod("read:files", e.currentTarget.files);
	},
	
	onFilesDropped: function(e) {
		console.debug("onFilesDropped", e);
		// if (!tests.formdata) {
		// 	console.log("FormData is not supported in this browser");
		// 	return;
		// }
		this.triggerMethod("read:files", e.originalEvent.dataTransfer.files);
	},
	
	onReadFiles: function(files) {
		// var formData = tests.formdata ? new FormData() : null;
		// var filesCollection = new FilesCollection();
		for (var i = 0; i < files.length; i++) {
			var fileModel = new FileModel(files[i]);
			// this.collection.add(fileModel);
			// formData.append('file', files[i]);
			this.triggerMethod("read:file", files[i], fileModel);
		}
	},

	onReadFile: function(file, fileModel) {
		var self = this;
		// if (tests.filereader === true && acceptedTypes[file.type] === true) {
			var reader = new FileReader();
			reader.onload = function(event) {
				var fileData = event.target.result;
				fileModel.set("data", fileData);
				console.log("fileModel:", fileModel.toJSON());
				self.collection.add(fileModel);
			};
			reader.readAsDataURL(file);
		// }  else {
		// 	// holder.innerHTML += '<p>Uploaded ' + file.name + ' ' + (file.size ? (file.size/1024|0) + 'K' : '');
		// 	console.log(file);
		// }
	}

})

var filesListView1 = new FilesListView({	el: '#file-uploader1', collection: new FilesCollection()});
var filesListView2 = new FilesListView({	el: '#file-uploader2', collection: new FilesCollection()});
filesListView1.render();
filesListView2.render();

// var holder = holder = document.getElementById('holder');
// var $form = $('.js--upload-form');
// var $input = $form.find('input[type="file"][multiple]');
// var $btnUpload = $('.js--upload-btn');

// if (isAdvancedUpload) {
//   $form.addClass('has-advanced-upload');
// }

// if (isAdvancedUpload) {

// 	var files = false;

// 	$form
// 		.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
// 			e.preventDefault();
// 			e.stopPropagation();
// 		})
// 		.on('dragover dragenter', function() {
// 			$form.addClass('is-dragover');
// 		})
// 		.on('dragleave dragend drop', function() {
// 			$form.removeClass('is-dragover');
// 		})
// 		.on('drop', onFilesDropped);
// 		// .on('drop', function(e) {
// 		// 	files = e.originalEvent.dataTransfer.files;
// 		// });
	
// 	$input.on('change', onFilesSelected);
	
// 	$btnUpload.on('click', function() {
		
// 		var ajaxData = new FormData($form.get(0));

// 		if (droppedFiles) {
// 			$.each( droppedFiles, function(i, file) {
// 				// debugger;
// 				console.log("BEFORE :", i, file, ajaxData);
// 			  	ajaxData.append( $input.attr('name'), file );
// 				console.log("AFTER	:", i, file,ajaxData);
// 			});
// 			// debugger;
			
// 		}
		// readFiles(files);
	// });
	
// 	function onFilesSelected(e) {
// 		console.debug("onFilesSelected", e);
// 		readFiles(e.currentTarget.files);
// 	}
	
// 	function onFilesDropped(e) {
// 		console.debug("onFilesDropped", e);
// 		if (!tests.formdata) {
// 			console.log("FormData is not supported in this browser");
// 			return;
// 		}
// 		readFiles(e.originalEvent.dataTransfer.files);
// 	}
	
// 	function readFiles(files) {
// 		var formData = tests.formdata ? new FormData() : null;
// 		var filesCollection = new FilesCollection();
// 		for (var i = 0; i < files.length; i++) {
// 			var fileModel = new FileModel(files[i]);
// 			filesCollection.add(fileModel);
// 			formData.append('file', files[i]);
// 			readFile(files[i], fileModel);
// 		}
// 	}

// 	function readFile(file, fileModel) {
// 		if (tests.filereader === true && acceptedTypes[file.type] === true) {
// 			var reader = new FileReader();
// 			reader.onload = function(event) {
// 				var fileData = event.target.result;
// 				fileModel.set("data", fileData);
// 				console.log("fileModel:", fileModel.toJSON());
// 			};
// 			reader.readAsDataURL(file);
// 		}  else {
// 			holder.innerHTML += '<p>Uploaded ' + file.name + ' ' + (file.size ? (file.size/1024|0) + 'K' : '');
// 			console.log(file);
// 		}
// 	}
	
// }

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js
  4. https://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/2.4.7/backbone.marionette.min.js