There is a table which displays files (one tr one file) there is a dropzonejs created on table so I can drag file and drop on table. I would like to add a "preview" as TR element of a table but I can't do this. This is how my preview template looks like:
<tr class="dz-preview">
<td><span class="name" data-dz-name></span></td>
<td><span class="size" data-dz-size></span></td>
<td colspan="5">
<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress> </div>
</div>
</td>
</tr>
Problem is that Dropzone.js does this:
Dropzone.createElement = function(string) {
var div;
div = document.createElement("div");
div.innerHTML = string;
return div.childNodes[0];
};
TR or TBODY is not valid child of DIV so it will be created as TEXT, TEXT doesn't have property querySelectorAll, and there is an error.
Is there a solution to use TR or TBODY as preview template?
Just redefine Dropzone.createElement function in your code.
In my case I use jQuery:
$(function() {
Dropzone.createElement = function(string) {
var el = $(string);
return el[0];
};
var dropzone = new Dropzone(document.body, options);
});
So here's a little fix in Dropzone.createElement function that fixes the problem:
Replace this:
div = document.createElement("div");
With this:
if (string.substr(0, 3) == '<tr'){
// Table elements can not be wrapped into a div
div = document.createElement("tbody");
} else {
div = document.createElement("div");
}
While I recommend #strikes answer as the most suitable answer. I'm attaching this code of a complete implementation using a tabular format which is a extension of #strikes answer and DropzoneJS bootstrap template
PS: Run snippet is functional, so you can try running the snippet here to see if it is properly working.
$('#allselect').change(function () {
var selections = document.getElementsByName('selection');
for( var i=0; i<selections.length; i++){
if(selections[i].checked == false) {
selections[i].checked = true;
}
else {
if(selections[i].checked == true) {
selections[i].checked = false;
}
}
};
});
</script>
<script>
// Get the template HTML and remove it from the doument
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
Dropzone.createElement = function(string) {
var el = $(string);
return el[0];
};
var myDropzone = new Dropzone(document.body, { // Make the whole body a dropzone
url: "{{ route('user.warehouse_images.store') }}", // Set the url
thumbnailWidth: 80,
paramName: "warehouse_image",
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: "#previews", // Define the container to display the previews
clickable: ".fileinput-button", // Define the element that should be used as click trigger to select files.
renameFile: function(file) {
var dt = new Date();
var time = dt.getTime();
return time+file.name;
},
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
});
myDropzone.on("addedfile", function (file) {
// Hookup the start button
file.previewElement.querySelector(".start").onclick = function () {
myDropzone.enqueueFile(file);
};
});
// Update the total progress bar
myDropzone.on("totaluploadprogress", function (progress) {
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on("sending", function (file) {
// Show the total progress bar when upload starts
document.querySelector("#total-progress").style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
// Hide the total progress bar when nothing's uploading anymore
myDropzone.on("queuecomplete", function (progress) {
document.querySelector("#total-progress").style.opacity = "0";
});
myDropzone.on("sending", function(file, xhr, formData){
formData.append("camera_id", "loremipsum");
console.log(file);
console.log(file.upload.filename);
console.log(xhr);
});
// Setup the buttons for all transfers
// The "add files" button doesn't need to be setup because the config
// `clickable` has already been specified.
document.querySelector("#actions .start").onclick = function () {
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
};
document.querySelector("#actions .cancel").onclick = function () {
myDropzone.removeAllFiles(true);
};
html, body {
height: 100%;
}
#actions {
margin: 2em 0;
}
/* Mimic table appearance */
div.table {
display: table;
}
div.table .file-row {
display: table-row;
}
div.table .file-row > div {
display: table-cell;
vertical-align: top;
border-top: 1px solid #ddd;
padding: 8px;
}
div.table .file-row:nth-child(odd) {
background: #f9f9f9;
}
/* The total progress gets shown by event listeners */
#total-progress {
opacity: 0;
transition: opacity 0.3s linear;
}
/* Hide the progress bar when finished */
#previews .file-row.dz-success .progress {
opacity: 0;
transition: opacity 0.3s linear;
}
/* Hide the delete button initially */
#previews .file-row .delete {
display: none;
}
/* Hide the start and cancel buttons and show the delete button */
#previews .file-row.dz-success .start,
#previews .file-row.dz-success .cancel {
display: none;
}
#previews .file-row.dz-success .delete {
display: block;
}
.custom-control {
position: relative;
display: block;
min-height: 1.5rem;
padding-left: 2.5rem;
}
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.0/dropzone.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.0/basic.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src='https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.7.0/dropzone.js'></script>
</head>
<body>
<!--File Dropzone-- -->
<div id="actions" class="row">
<div class="col-lg-1">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="allselect">
<label for="allselect" class="custom-control-label"></label>
</div>
</div>
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button dz-clickable">
<i class="fa fa-plus"></i>
<span>Add files...</span>
</span>
<button type="submit" class="btn btn-primary start">
<i class="fa fa-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="fa fa-ban"></i>
<span>Cancel upload</span>
</button>
</div>
<div class="col-lg-4">
<!-- The global file processing state -->
<span class="fileupload-process">
<div id="total-progress" class="progress progress-striped active" role="progressbar" aria-valuemin="0"
aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress=""></div>
</div>
</span>
</div>
</div>
<div class="row">
<table class="table table-striped">
<thead>
<tr>
<th>Select</th>
<th>Image Preview</th>
<th>Image Name</th>
<th>Camera</th>
<th>Date</th>
<th>Progress</th>
<th>Actions</th>
</tr>
</thead>
<tbody class="table table-striped files" id="previews">
<tr id="template" class="file-row">
<td>
<input type="checkbox" name="selection">
</td>
<td>
<span class="preview"><img data-dz-thumbnail/></span>
</td>
<td>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</td>
<td>
<p class="cameraText"> Camera Not set</p>
</td>
<td>
<p class="timestamp">Date Not Set</p>
</td>
<td>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0"
aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;"
data-dz-uploadprogress></div>
</div>
</td>
<td>
<button class="btn btn-primary start">
<i class="fa fa-upload"></i>
<span>Start</span>
</button>
<button data-dz-remove class="btn btn-warning cancel">
<i class="fa fa-ban"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="fa fa-trash"></i>
<span>Delete</span>
</button>
</td>
<td>
<p class="camera" style="visibility: hidden"></p>
</td>
</tr>
</tbody>
</table>
</div>
</body>
Related
I have a small tool for scrum teams to track people in the meeting. Now we are more people, one team is added and right now it seems more logical to re-arrange the elements.
Now if you click on team1/team2/team3 button, the names are sorted in 3 columns and next to each other. I want to change this, to 3 columns, but every team will have it's own column. So, team1 names will fill up the first column and the names in this team will come under each other. After that if I click on team2, the names of team2 will fill up the second column and the team3 will fill up the third column. I assume on every team button click the script should create one column and fill up this column, on the second team button click it will again create one column next to the first also on the third time. Is this possible? Thank you very much.
This is the one page working version, all names are randomly generated, completely anonym:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Team Members</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<style>
.footer {
position: fixed;
left: 0;
bottom: 0;
right: 0;
z-index: 10;
}
.alert.member-clicked {
text-decoration-line: line-through;
background-color: #ddd;
border-color: #ddd;
}
.alert.member-absent {
text-decoration-line: line-through;
background-color: #f8d7da;
border-color: #f8d7da;
}
.copyright {
margin-top: 10px;
margin-right: 10px;
text-align: right;
}
.form-inline.form-members .input-group {
display: inline-table;
vertical-align: middle;
}
.form-inline.form-members .input-group .input-group-btn {
width: auto;
}
h2 {
margin-bottom: 20px;
}
</style>
</head>
<body>
<center>
<div class="container">
<h2 class="text text-success text-center">My Team Members</h2>
<div id="memberlist" class="row"></div>
</div>
<footer class="footer">
<div class="container">
<!-- Input for members -->
<div class="form-inline form-members">
<div class="input-group">
<input type="text" class="form-control" placeholder="Add member" id="text" value="Alasdair Mckee">
<div class="input-group-btn">
<button class="btn btn-success btn-addmember"><i class="glyphicon glyphicon-plus"></i></button>
</div>
</div>
<button class="btn btn-success" data-team="team1"><i class="glyphicon glyphicon-plus"></i> Team1</button>
<button class="btn btn-success" data-team="team2"><i class="glyphicon glyphicon-plus"></i> Team2</button>
<button class="btn btn-success" data-team="team3"><i class="glyphicon glyphicon-plus"></i> Team3</button>
</div>
<div class="form-group hidden">
<label for="exampleFormControlTextarea1">Team1</label>
<textarea class="form-control" id="team1" rows="9">
Bentley Parrish
Hunter Pineda
Ammar Burks
Tanya Vang
Aimie Ewing
Anabella Chan
Amayah Sparks
Priyanka Cooke
Boyd Pacheco
Mai Lynch
</textarea>
<label for="exampleFormControlTextarea1">Team2</label>
<textarea class="form-control" id="team2" rows="9">
Alan Rangel
Ikra Knowles
Chelsea Avalos
Aysha Glenn
Margaret Couch
Effie Corbett
Yassin Arias
Caspian Rice
</textarea>
<label for="exampleFormControlTextarea1">Team3</label>
<textarea class="form-control" id="team3" rows="9">
Armani Curran
Monica Kemp
Nur Davis
Hashir Dodson
Ty Hagan
Aariz Rowley
</textarea>
</div>
</div>
<p class="copyright">Created by: Me • me#me.com • ver 1.5</p>
</footer>
</center>
<script>
$(document).ready(function() {
var memberList = $("#memberlist");
memberList.on("click", ".alert", function () {
$(this).toggleClass("member-clicked");
});
memberList.on("click", ".close", function () {
var memberColumn = $(this).parent().parent();
memberColumn.fadeOut();
});
$(".btn-addmember").click(function () {
var newMember = $("#text").val().trim();
if (newMember) {
addMember(newMember);
} else {
alert("Please, enter the name of the member");
}
$("#text").val("");
});
$(".btn[data-team]").click(function () {
addTeam($(this).data("team"));
});
function addMember(member) {
member = member.trim();
if (member) {
memberList.append(
`<div class="col-xs-6 col-sm-4"><div class="alert alert-success">` +
`<span class="close" aria-label="close">×</span><b>` +
member +
`</b></div></div>`
);
}
}
function addTeam(id) {
var team = $("#" + id)
.val()
.trim();
if (team) {
var members = team.split("\n");
console.log(members);
for (var i = 0; i < members.length; i++) {
addMember(members[i]);
}
}
}
$(document).on('dblclick', '.alert', function() {
$(this).toggleClass("member-absent");
});
});
</script>
</body>
</html>
I think you need to use 3 member lists instead of one.
var memberList1 = $("#listteam1");
var memberList2 = $("#listteam2");
var memberList3 = $("#listteam3");
that means the layout will change:
<div class="row">
<div class="col-xs-6 col-sm-4">
<h3>Team 1</h3>
<div class="column" id="listteam1">
</div>
</div>
<div class="col-xs-6 col-sm-4">
<h3>Team 2</h3>
<div class="column" id="listteam2">
</div>
</div>
<div class="col-xs-6 col-sm-4">
<h3>Team 3</h3>
<div class="column" id="listteam3">
</div>
</div>
</div>
also, addMember needs to take the list name as an argument
function addMember(member, list) {
member = member.trim();
if (member) {
$("#list" + list).append(
`<div class="alert alert-success">` +
`<span class="close" aria-label="close">×</span><b>` +
member +
`</b></div>`
);
}
}
please find the whole script here: https://pastebin.com/VQEVKCaF
I've got this button in which I'd like to insert an icon with JavaScript:
<button id="chat5" onclick="actualizarIdChat('{{ elemento.pk }}')" class="btn btn-secondary" style="background-color: maroon; border-color: transparent;border-radius: 15px;height: 60px;margin: 10px 0px 10px 0px;width: 90%;" type="button">
<img class="border rounded-circle" style="width: 50px;height: 50px;border-color: transparent;" src="{{ elemento.producto.info_producto.contenido_multimedia.0.contenido_url }}">
{{ elemento.producto.info_producto.nombre }}
</button>
This is the code I've defined to make it work, but it does nothing.
var idChat = 'chat5';
var icon = document.createElement("div");
icon.innerHTML = '<i class="fa fa-envelope"></i>';
document.getElementById(idChat).appendChild(icon);
How could I do it?
Update javascript part, it looks like:
var buttonElement = document.getElementById("chat5");
buttonElement.innerHTML = buttonElement.innerHTML + '<i class="fa fa-envelope"></i>';
It will work
How do I get the function to always remember the sequence of the last removed .items so that I may undo as many items that were removed before the undo timeout occurs?
I want to be able to quickly remove all .items and then press undo to replace all three, one by one where pressing the undo button replaces the last removed item.
Currently I can only replace the last removed .item.
var undo = false;
var remove;
var timeout;
$(document).ready(function() {
/*DELETE*/
$('body').on('click', '.fa-times', function() {
if ($('.item').hasClass("temp_deleted")) {
$('.item.temp_deleted').remove();
}
remove = $(this).parent().parent();
var undo_time = 10000;
remove.animate({
height: "0px"
}, 200, function() {
$(this).addClass('temp_deleted').hide();
});
function_undo(remove, undo);
//undo
$('.undo').addClass('active');
clearTimeout(timeout);
timeout = setTimeout(function() {
$('.undo').removeClass('active');
if (undo === false) {
$('.item.temp_deleted').remove();
}
}, undo_time);
});
/*UNDO*/
$('.undo div').click(function() {
undo = true;
function_undo(remove, undo);
$(this).parent().removeClass('active');
});
});
function function_undo(remove, undo) {
if (undo == true) {
remove.css('height', 'auto');
remove.show();
remove.removeClass('temp_deleted');
}
}
.item {
width: 100px;
height: 50px;
border: 2px solid
}
.actions span.fa-times:hover {
color: #fe4444;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div class="item">
<div class="actions">
<span class="fa fa-times"></span>
</div>
</div>
<div class="item">
<div class="actions">
<span class="fa fa-times"></span>
</div>
</div>
<div class="item">
<div class="actions">
<span class="fa fa-times"></span>
</div>
</div>
</div>
</div>
<div class="undo">
<div>
<span class="fa fa-undo"></span> Undo
</div>
</div>
As I said, you can save them in an array. When you remove it, push it in the array. When you want to undo something, pop it out.
And by the way, as #LexJacobs said, don't remove it. just hide it.
Not sure if this is what you want. But I'm trying to structure this out.
var undo = false;
var timeout;
var arr = [];
$(document).ready(function() {
/*DELETE*/
$('body').on('click', '.fa-times', function() {
if ($('.item').hasClass("temp_deleted")) {
$('.item.temp_deleted').hide();
}
remove = $(this).parent().parent();
var undo_time = 10000;
remove.animate({
height: "0px"
}, 200, function() {
$(this).addClass('temp_deleted').hide();
});
function_undo(remove, undo);
//undo
$('.undo').addClass('active');
clearTimeout(timeout);
timeout = setTimeout(function() {
$('.undo').removeClass('active');
if (undo === false) {
$('.item.temp_deleted').hide();
}
}, undo_time);
arr.push(remove);
});
/*UNDO*/
$('.undo div').click(function() {
undo = true;
var remove = arr.pop();
function_undo(remove, undo);
$(this).parent().removeClass('active');
});
});
function function_undo(remove, undo) {
if (undo == true) {
remove.css('height', 'auto');
remove.show();
remove.removeClass('temp_deleted');
}
}
.item {
width: 100px;
height: 50px;
border: 2px solid
}
.actions span.fa-times:hover {
color: #fe4444;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="list">
<div class="item">
<div class="actions">
<span class="fa fa-times"></span> 1
</div>
</div>
<div class="item">
<div class="actions">
<span class="fa fa-times"></span> 2
</div>
</div>
<div class="item">
<div class="actions">
<span class="fa fa-times"></span> 3
</div>
</div>
</div>
</div>
<div class="undo">
<div>
<span class="fa fa-undo"></span> Undo
</div>
</div>
I am attempting to change the style of a bootstrap progress bar, and place the current percentage value in it. Clicking the button allows the value (width) to change, but not the background or text value.
Here is the code.
$(function() {
$(document).ready(function() {
$("#progress-bar1").css("width", "50%");
$("#progress-bar1").attr("aria-valuenow", "50%");
});
});
$(document).ready(function() {
$("#btnSubmit").click(function() {
$('#progress-bar1').css("width", "10%");
$("#progress-bar1").attr("progress-bar-danger", "10");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<div class="progress">
<div class="progress-bar progress-bar-striped active" id="progress-bar1" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
50%
</div>
</div>
<input id="btnSubmit" type="submit" value="Update" />
You need to add the class progress-bar-danger and update the text to 10%:-
$("#btnSubmit").click(function(){
$('#progress-bar1')
.addClass('progress-bar-danger') // change to red
.css("width", "10%") // change width to 10%
.attr('aria-valuenow', 10) // change value to 10
.text('10%'); // change text to 10%
});
Fiddle
You can create a jQuery plugin to set the progress value.
(function($) {
$.progressArray = ['danger', 'warning', 'info', 'success'];
$.fn.setProgress = function(percentVal) {
percentVal = percentVal === 0 ? 0 : percentVal || parseInt(this.attr('aria-valuenow'), 10) || 0;
percentVal = Math.min(100, Math.max(0, percentVal));
var progressIndex = Math.ceil(percentVal / 25) - 1;
return this.css('width', percentVal + '%')
.attr('aria-valuenow', percentVal)
.text(percentVal + '%')
.removeClass($.progressArray.map(cls => 'progress-bar-' + cls).join(' '))
.addClass('progress-bar-' + $.progressArray[progressIndex]);
};
$.fn.addProgress = function(percentVal) {
return this.setProgress((parseInt(this.attr('aria-valuenow'), 10) || 0) + percentVal);
};
$.fn.setTooltipText = function(text) {
return this.tooltip('hide').attr('data-original-title', text).tooltip('fixTitle');
};
$.fn.replaceTooltipText = function(regex, repl) {
return this.setTooltipText(this.attr('data-original-title').replace(regex, repl));
};
})(jQuery);
$(function() {
$('[data-toggle="tooltip"]').tooltip({ placement : 'bottom' });
var $progressBar = $("#progress-bar-1").setProgress();
$('#btn-decr').on('click', function() {
$progressBar.addProgress(-parseInt($('#progress-step').val(), 10));
});
$('#btn-incr').on('click', function() {
$progressBar.addProgress(parseInt($('#progress-step').val(), 10));
});
$('#progress-step').on('keyup change', function() {
var pattern = /\d+(\.\d+)?/g, replacement = $('#progress-step').val();
$('#btn-decr').replaceTooltipText(pattern, replacement);
$('#btn-incr').replaceTooltipText(pattern, replacement);
});
});
.tooltip-inner {
font-size: 1.5em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-6">
<div class="progress">
<div class="progress-bar progress-bar-striped active" id="progress-bar-1" role="progressbar"
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<div class="row align-items-center">
<div class="col-sm-5 col-md-2 text-center">
<button type="button" class="btn btn-primary" id="btn-decr"
data-toggle="tooltip" title="Decrease Progress by 25%">
<i class="fa fa-arrow-down"></i> %
</button>
</div>
<div class="col-sm-2 col-md-2">
<input type="number" class="form-control" id="progress-step"
min="0" max="100" step="10" data-buttons="true" value="25" />
</div>
<div class="col-sm-5 col-md-2 text-center">
<button type="button" class="btn btn-primary" id="btn-incr"
data-toggle="tooltip" title="Increase Progress by 25%">
<i class="fa fa-arrow-up"></i> %
</button>
</div>
</div>
</div>
You would have to modify the "background-image" css property. In your HTML code, try adding the following, as an example:
<style>
#progress-bar1{
background-image: none;
background-color: green;
}
</style>
Essentially what I am trying to do, is allow people to add files, then on button press upload the images to Firebase storage. I decided to use Dropzone.js because of the well written and customizable the package is but I am still stumped.
I have this code which allows me to upload multiple images to Firebase, however, I want it to fit the framework seen below this code:
HTML
<input type="file" id="file" name="file" multiple/>
JS
var auth = firebase.auth();
var storageRef = firebase.storage().ref();
//Handle waiting to upload each file using promise
function uploadImageAsPromise (imageFile) {
return new Promise(function (resolve, reject) {
var storageRef = firebase.storage().ref("/sth/"+imageFile.name);
//Upload file
var task = storageRef.put(imageFile);
//Update progress bar
task.on('state_changed',
function progress(snapshot){
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
},
function error(err){
},
function complete(){
var downloadURL = task.snapshot.downloadURL;
}
);
});
}
window.onload = function() {
document.getElementById('file').addEventListener('change', function(e){
//Get files
for (var i = 0; i < e.target.files.length; i++) {
var imageFile = e.target.files[i];
uploadImageAsPromise(imageFile);
}
});
document.getElementById('file').disabled = true;
auth.onAuthStateChanged(function(user) {
if (user) {
document.getElementById('file').disabled = false;
} else {
console.log('You need to sign in.');
}
});
}
What I'm Trying To Accomplish
I would like to incorporate the above upload functionality into the below snippet. When I press submit id like the progress bar to show and the files to be uploaded. Dropzone said I am supposed to specify the function where it says URL: but I don't know how to reference it. Also, dropzone said the function must return the downloaded URL.
// Get the template HTML and remove it from the doument
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
var submitButton = document.querySelector('#submit-button');
var myDropzone = new Dropzone(document.body, { // Make the whole body a dropzone
url: "/", // Set the url
thumbnailWidth: 80,
thumbnailHeight: 80,
parallelUploads: 20,
previewTemplate: previewTemplate,
autoQueue: false, // Make sure the files aren't queued until manually added
previewsContainer: "#previews", // Define the container to display the previews
clickable: ".fileinput-button" // Define the element that should be used as click trigger to select files.
});
// Update the total progress bar
myDropzone.on("totaluploadprogress", function(progress) {
document.querySelector("#total-progress .progress-bar").style.width = progress + "%";
});
myDropzone.on("sending", function(file) {
// Show the total progress bar when upload starts
document.querySelector("#total-progress").style.opacity = "1";
// And disable the start button
file.previewElement.querySelector(".start").setAttribute("disabled", "disabled");
});
submitButton.addEventListener('click', function(){
myDropzone.enqueueFiles(myDropzone.getFilesWithStatus(Dropzone.ADDED));
myDropzone.on("queuecomplete", function(progress) {
document.querySelector("#total-progress").style.opacity = "0";
//DO STUFF
});
});
#actions {
margin: 2em 0;
}
/* Mimic table appearance */
div.table {
display: table;
}
div.table .file-row {
display: table-row;
}
div.table .file-row > div {
display: table-cell;
vertical-align: top;
border-top: 1px solid #ddd;
padding: 8px;
}
div.table .file-row:nth-child(odd) {
background: #f9f9f9;
}
/* The total progress gets shown by event listeners */
#total-progress {
opacity: 0;
transition: opacity 0.3s linear;
}
/* Hide the progress bar when finished */
#previews .file-row.dz-success .progress {
opacity: 0;
transition: opacity 0.3s linear;
}
/* Hide the delete button initially */
#previews .file-row .delete {
display: none;
}
/* Hide the start and cancel buttons and show the delete button */
#previews .file-row.dz-success .start,
#previews .file-row.dz-success .cancel {
display: none;
}
#previews .file-row.dz-success .delete {
display: block;
}
<!DOCTYPE html>
<!--[if IE 9]> <html lang="zxx" class="ie9"> <![endif]-->
<!--[if gt IE 9]> <html lang="zxx" class="ie"> <![endif]-->
<!--[if !IE]><!-->
<html dir="ltr" lang="zxx">
<!--<![endif]-->
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<!-- Import and configure the Firebase SDK -->
<script src="https://www.gstatic.com/firebasejs/4.9.0/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "<your-api-key>",
authDomain: "<your-auth-domain>",
databaseURL: "<your-database-url>",
projectId: "<your-project-id>",
storageBucket: "<your-storage-bucket>",
messagingSenderId: "<your-messaging-id>"
};
firebase.initializeApp(config);
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.2.0/dropzone.js"></script>
</head>
<body class=" ">
<!-- banner start -->
<!-- ================ -->
<div class="pv-40 banner light-gray-bg">
<div class="container clearfix">
<h3>Add Images</h3>
<div id="actions" class="row">
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
</span>
</div>
</div>
<div class="table table-striped files" id="previews">
<div id="template" class="file-row">
<!-- This is used as the file preview template -->
<div>
<span class="preview"><img data-dz-thumbnail /></span>
</div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</div>
<div>
<button data-dz-remove class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
<button data-dz-remove class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- banner end -->
<!-- main-container start -->
<!-- ================ -->
<section class="main-container padding-ver-clear">
<div class="container pv-40">
<div style="text-align: center;">
<button id="submit-button" type="submit" value="Submit" class="btn btn-danger btn-lg start">Submit <i class="fa fa-external-link"></i></button>
<div class="col-lg-5">
<!-- The global file processing state -->
<span class="fileupload-process">
<div id="total-progress" class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</span>
</div>
</div>
</div>
</section>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
</body>
</html>
You could use the 'addedfile' event to trigger your custom upload function like this:
myDropzone.on("addedfile", function(){
uploadImageAsPromise(file);
});
and omit the dropzone upload functionality completely.
To get the progress data use only the firebase put().on(state_changed) method and omit dropzone progress again.
You've probably solved this by now, so I'd love some feedback on this answer since I am working with dropzone and firebase myself at the moment.