Firebase Storage and Dropzone.js multiple image upload on button press - javascript

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.

Related

If buttons of item were inactive for 2 sec - make action

I would like to implement such logic:
User clicks on "Plus" or "Minus" button.
If the user don't click at any of those buttons for 2 seconds, then we assume that current quantity should be sent to the server.
Right now, I have three buttons:
"Plus" - increments quantity by 1 and changes the value at page.
"Minus" - decreases quantity by 1 and changes the value at page.
"Confirm" - The button that sends request with current quantity parameter to Spring Boot controller and changes quantity on server side.
I would prefer to avoid this button, because it adds complexity.
Is there a convenient way to get rid of the confirm button?
The only way I know how we can do this is by sending request to controller on each "Plus" or "Minus" button click.
But it seems that this approach will be inefficient.
$(document).ready(function () {
//include csrf for every ajax call
$(function () {
let token = $("meta[name='_csrf']").attr("content");
let header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function (event, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$(".plusForm").submit(function (event) {
event.preventDefault();
let $prodCount = $(this).parent().parent().parent().find(".prodCount span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(++currentQuantity);
});
$(".minusForm").submit(function (event) {
event.preventDefault();
let $prodCount = $(this).parent().parent().parent().find(".prodCount span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(--currentQuantity);
});
$(".changedQuantityForm").submit(function (event) {
event.preventDefault();
let $prodCount = $(this).parent().parent().parent().find(".prodCount span");
let quantity = parseInt($prodCount.text());
let productId = $(this).parent().parent().parent().parent().find(
'.product-id').val();
changeQuantityAjax(productId, quantity);
});
function changeQuantityAjax(id, quantity) {
console.log("quantity changed on server side");
/* $.ajax({
type: "PUT",
contentType: "application/json",
url: "/rest/cart/" + id + "?quantity=" + quantity,
data: {
"quantity": quantity
},
success: function () {
console.log('SUCCESS ' + id + ' ' + quantity);
// alert(name + ' was deleted')
},
error: function () {
console.log('ERROR ' + id + ' ' + quantity);
}
}); */
}
})
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"
rel="stylesheet" media="screen"/>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css">
<div class="row justify-content-center">
<div class="col mb-4 prodItem">
<div class="card border-primary" style="height: 34rem; width: 26rem;">
<div class="view overlay">
<img class="card-img-top img-fluid"
src="https://cdn.pixabay.com/photo/2018/10/05/23/24/chicken-3727097_1280.jpg"
style="height : 18rem;" alt="Card image cap">
<div class="mask rgba-white-slight"></div>
</div>
<div class="card-body">
<h3><span>Chicken</span></h3>
<div class="float-right">
<h2 class="card-title"><span>1000</span> $</h2>
</div>
<br>
<br>
<br>
<div class="form-control">
<div class="row prodCount" style="margin: auto; font-size: 17px">
<p> In cart : &nbsp</p>
<span>0</span>
<div class="row float-right" style="margin: auto">
<form class="plusForm">
<button type="submit" class="btn-sm">
<i class="fas fa-plus-circle fa-w-16 fa-3x text-danger"></i>
</button>
</form>
<form class="minusForm">
<button type="submit" class="btn-sm">
<i class="fa fa-minus-circle fa-w-16 fa-3x" aria-hidden="true"></i>
</button>
</form>
<form class="changedQuantityForm">
<button type="submit" class="btn-sm">
<i class="fas fa-check fa-w-16 fa-3x text-success"></i>
</button>
</form>
</div>
</div>
</div>
<br>
</div> <!-- card-body -->
</div> <!-- card -->
</div>
Fiddle
PC: It seems that my question is related to this topic(https://stackoverflow.com/a/7762539/14308420).
But I'm not sure if I should apply it in my case and how to do it.
I extracted the logic of submit button to function updateQuantityOnServer(button). And after adding this line:
changedQuantityTimeout = setTimeout(updateQuantityOnServer(this), 1000);
I got a warning:
Argument type void is not assignable to parameter type TimerHandler Type void is not assignable to type string | Function Type void is not assignable to type Function.
As I understand, it's caused because I send button as parameter. But I use this button to get parameters...
Look at the changeQuantityAjax function for the implementation of clearTimeout and setTimeout together, making a "minimal" delay of 2 seconds after the last user action.
From each button click, this was passed to the getIdandQuantity function.
It does not change much things in the logic, but notice the .parents() instead of parent().parent().parent().
$(document).ready(function() {
//include csrf for every ajax call
$(function() {
let token = $("meta[name='_csrf']").attr("content");
let header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(event, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
$(".plusForm").submit(function(event) {
event.preventDefault();
let $prodCount = $(this).parents(".prodCount").find("span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(++currentQuantity);
getIdandQuantity(this);
});
$(".minusForm").submit(function(event) {
event.preventDefault();
let $prodCount = $(this).parents(".prodCount").find("span");
let currentQuantity = parseInt($prodCount.text());
$prodCount.text(--currentQuantity);
getIdandQuantity(this);
});
// That is the function to retreive the id and quantity from the clicked button
function getIdandQuantity(btn) {
let $parent = $(btn).parents(".prodCount");
let quantity = parseInt($parent.find("span").text());
let productId = $parent.find('.product-id').val();
changeQuantityAjax(productId, quantity);
}
// A variable to store the refence to the pending setTimeout
let ajaxTimeout
function changeQuantityAjax(id, quantity) {
// Clear any existing setTimeout
clearTimeout(ajaxTimeout)
// Set a 2 seconds timeout
ajaxTimeout = setTimeout(function() {
console.log("quantity changed on server side");
/* $.ajax({...}) */
}, 2000)
}
})
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" media="screen" />
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css">
<div class="row justify-content-center">
<div class="col mb-4 prodItem">
<div class="card border-primary" style="height: 34rem; width: 26rem;">
<div class="view overlay">
<img class="card-img-top img-fluid" src="https://cdn.pixabay.com/photo/2018/10/05/23/24/chicken-3727097_1280.jpg" style="height : 18rem;" alt="Card image cap">
<div class="mask rgba-white-slight"></div>
</div>
<div class="card-body">
<h3><span>Chicken</span></h3>
<div class="float-right">
<h2 class="card-title"><span>1000</span> $</h2>
</div>
<br>
<br>
<br>
<div class="form-control">
<div class="row prodCount" style="margin: auto; font-size: 17px">
<p> In cart : &nbsp</p>
<span>0</span>
<div class="row float-right" style="margin: auto">
<form class="plusForm">
<button type="submit" class="btn-sm">
<i class="fas fa-plus-circle fa-w-16 fa-3x text-danger"></i>
</button>
</form>
<form class="minusForm">
<button type="submit" class="btn-sm">
<i class="fa fa-minus-circle fa-w-16 fa-3x" aria-hidden="true"></i>
</button>
</form>
</div>
</div>
</div>
<br>
</div>
<!-- card-body -->
</div>
<!-- card -->
</div>
Additionnally! You could easilly merge the 4 functions above (2 click handlers, getIdandQuantity and changeQuantityAjax) into one single click handler.
$(document).ready(function() {
//include csrf for every ajax call
$(function() {
let token = $("meta[name='_csrf']").attr("content");
let header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(event, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
// A variable to store the refence to the pending setTimeout
let ajaxTimeout
$(".plusForm, .minusForm").submit(function(event) {
event.preventDefault();
// Get the elements needed, the product is and the quantity shown
let $parent = $(this).parents(".prodCount");
let id = $parent.find('.product-id').val();
let $prodCount = $parent.find("span")
let currentQuantity = parseInt($prodCount.text());
// Increment OR decrement the quantity
let quantity = ($(this).hasClass("plusForm")) ? ++currentQuantity : --currentQuantity
// Update the shown quantity
$prodCount.text(quantity)
// Clear any existing setTimeout
clearTimeout(ajaxTimeout)
// Set a 2 seconds timeout
ajaxTimeout = setTimeout(function() {
console.log("quantity changed on server side");
/* $.ajax({...}) */
}, 2000)
});
})
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" media="screen" />
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css">
<div class="row justify-content-center">
<div class="col mb-4 prodItem">
<div class="card border-primary" style="height: 34rem; width: 26rem;">
<div class="view overlay">
<img class="card-img-top img-fluid" src="https://cdn.pixabay.com/photo/2018/10/05/23/24/chicken-3727097_1280.jpg" style="height : 18rem;" alt="Card image cap">
<div class="mask rgba-white-slight"></div>
</div>
<div class="card-body">
<h3><span>Chicken</span></h3>
<div class="float-right">
<h2 class="card-title"><span>1000</span> $</h2>
</div>
<br>
<br>
<br>
<div class="form-control">
<div class="row prodCount" style="margin: auto; font-size: 17px">
<p> In cart : &nbsp</p>
<span>0</span>
<div class="row float-right" style="margin: auto">
<form class="plusForm">
<button type="submit" class="btn-sm">
<i class="fas fa-plus-circle fa-w-16 fa-3x text-danger"></i>
</button>
</form>
<form class="minusForm">
<button type="submit" class="btn-sm">
<i class="fa fa-minus-circle fa-w-16 fa-3x" aria-hidden="true"></i>
</button>
</form>
</div>
</div>
</div>
<br>
</div>
<!-- card-body -->
</div>
<!-- card -->
</div>

User name are duplicated for each login in html?

I have been using firebase cloud firestore. My issue is when user logged in, the user name displays on header with drop down option account, payment and logout. When user logged out and login again with same or another account details user name keeps on adding on header with previous logged in user name.
Note: here i am using firebase authentication and cloud firestore database.
here is my screen shot:
$(document).ready(function(){
//initialize the firebase app
var config = {
apiKey: "AIzaSyBDwqFKPt4D0eIspjsziweLI0nc49BRDrU",
authDomain: "cloudthrifty-demo.firebaseapp.com",
databaseURL: "https://cloudthrifty-demo.firebaseio.com",
projectId: "cloudthrifty-demo",
storageBucket: "cloudthrifty-demo.appspot.com",
messagingSenderId: "638814042535"
};
firebase.initializeApp(config);
//create firebase references
var Auth = firebase.auth();
var dbRef = firebase.database();
var contactsRef = dbRef.ref('contacts')
var usersRef = dbRef.ref('users')
var auth = null;
var db = firebase.firestore();
//Register
$('#registerForm').on('submit', function (e) {
e.preventDefault();
$('#registerModal').modal('hide');
$('#messageModalLabel').html(spanText('<i class="fa fa-cog fa-spin"></i>', ['center', 'info']));
$('#messageModal').modal('show');
var data = {
email: $('#registerEmail').val(), //get the email from Form
firstName: $('#registerFirstName').val(), // get firstName
lastName: $('#registerLastName').val(), // get lastName
};
var passwords = {
password : $('#registerPassword').val(), //get the pass from Form
cPassword : $('#registerConfirmPassword').val(), //get the confirmPass from Form
}
if( data.email != '' && passwords.password != '' && passwords.cPassword != '' ){
if( passwords.password == passwords.cPassword ){
//create the user
firebase.auth().createUserWithEmailAndPassword(data.email, passwords.password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
})
.then(function(user){
//now user is needed to be logged in to save data
auth = user;
//now saving the profile data
var uid = firebase.auth().currentUser.uid;
console.log(uid);
db.collection("users").doc(uid).set({
name: data.firstName
})
.then(function() {
console.log("Document successfully written!");
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
})
.catch(function(error) {
console.error("Error writing document: ", error);
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
});
$('#messageModalLabel').html(spanText('Success!', ['center', 'success']))
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
})
.catch(function(error){
console.log("Error creating user:", error);
$('#messageModalLabel').html(spanText('ERROR: '+error.code, ['danger']))
});
} else {
//password and confirm password didn't match
$('#messageModalLabel').html(spanText("ERROR: Passwords didn't match", ['danger']))
}
}
});
//Login
$('#loginForm').on('submit', function (e) {
e.preventDefault();
$('#loginModal').modal('hide');
$('#messageModalLabel').html(spanText('<i class="fa fa-cog fa-spin"></i>', ['center', 'info']));
$('#messageModal').modal('show');
if( $('#loginEmail').val() != '' && $('#loginPassword').val() != '' ){
//login the user
var data = {
email: $('#loginEmail').val(),
password: $('#loginPassword').val()
};
firebase.auth().signInWithEmailAndPassword(data.email, data.password)
.then(function(authData) {
auth = authData;
$('#messageModalLabel').html(spanText('Success!', ['center', 'success']))
$('#loginModal').modal('hide');
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
})
.catch(function(error) {
console.log("Login Failed!", error);
$('#messageModalLabel').html(spanText('ERROR: '+error.code, ['danger']))
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
});
}
});
$('#logout').on('click', function(e) {
e.preventDefault();
firebase.auth().signOut().then(function() {
// Sign-out successful.
// window.location='index.html';
}).catch(function(error) {
// An error happened.
});
});
//save contact
$('#contactForm').on('submit', function( event ) {
event.preventDefault();
if( auth != null ){
if( $('#name').val() != '' || $('#email').val() != '' ){
contactsRef.child(auth.uid)
.push({
name: $('#name').val(),
email: $('#email').val(),
location: {
city: $('#city').val(),
state: $('#state').val(),
zip: $('#zip').val()
}
})
document.contactForm.reset();
} else {
alert('Please fill at-lease name or email!');
}
} else {
//inform user to login
}
});
// firebase.auth().onAuthStateChanged(function(user) {
// if (user) {
// auth = user;
// $('body').removeClass('auth-false').addClass('auth-true');
// usersRef.child(user.uid).once('value').then(function (data) {
// var info = data.val();
// console.log(info);
// // if(user.photoUrl) {
// // $('.user-info img').show();
// // $('.user-info img').attr('src', user.photoUrl);
// // $('.user-info .user-name').hide();
// // } else if(user.displayName) {
// // $('.user-info img').hide();
// // $('.user-info').append('<span class="user-name">'+user.displayName+'</span>');
// // } else if(info.firstName) {
// // $('.user-info img').hide();
// // $('.user-info').append('<span class="user-name">'+info.firstName+'</span>');
// // }
// });
// contactsRef.child(user.uid).on('child_added', onChildAdd);
// } else {
// // No user is signed in.
// $('body').removeClass('auth-true').addClass('auth-false');
// auth && contactsRef.child(auth.uid).off('child_added', onChildAdd);
// $('#contacts').html('');
// auth = null;
// }
// });
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
auth = user;
var uid = firebase.auth().currentUser.uid;
console.log(uid);
$('body').removeClass('auth-false').addClass('auth-true');
db.collection("users").doc(uid)
.onSnapshot(function(doc) {
console.log("Current data: ", doc.data());
var name = doc.data().name
$('.user-info').append('<span class="user-name">'+name+'<span class="caret"></span></span>');
console.log(name);
});
} else {
// User is signed out.
$('body').removeClass('auth-true').addClass('auth-false');
auth && contactsRef.child(auth.uid).off('child_added', onChildAdd);
$('#contacts').html('');
auth = null;
}
});
});
function onChildAdd (snap) {
$('#contacts').append(contactHtmlFromObject(snap.key, snap.val()));
}
//prepare contact object's HTML
function contactHtmlFromObject(key, contact){
return '<div class="card contact" style="width: 18rem;" id="'+key+'">'
+ '<div class="card-body">'
+ '<h5 class="card-title">'+contact.name+'</h5>'
+ '<h6 class="card-subtitle mb-2 text-muted">'+contact.email+'</h6>'
+ '<p class="card-text" title="' + contact.location.zip+'">'
+ contact.location.city + ', '
+ contact.location.state
+ '</p>'
// + 'Card link'
// + 'Another link'
+ '</div>'
+ '</div>';
}
function spanText(textStr, textClasses) {
var classNames = textClasses.map(c => 'text-'+c).join(' ');
return '<span class="'+classNames+'">'+ textStr + '</span>';
}
*, *:before, *:after {
box-sizing: border-box;
}
html {
overflow-y: scroll;
}
body {
background: #fff;
font-family: 'Titillium Web', sans-serif;
}
a {
text-decoration: none;
color: #4F5459;
transition: .5s ease;
}
a:hover {
color: #71D72C;
}
/* #media only screen and (min-width: 640px) and (orientation: portrait) {
}
#media only screen and (min-width: 640px) and (orientation: landscape) {
} */
.userAuth {
display: block;
margin: 0px 0 0;
}
.modal-header:last-child{
border-bottom: 0;
}
.card {
display: inline-block;
margin: 1em;
max-width: calc(25% - 2em);
}
.user-info {
display: inline-block;
margin: 0 0.5em;
}
.user-info img{
display: inline-block;
max-width: 2em;
}
.auth-true .authenticated,
.auth-false .unauthenticated {
display: block;
}
.auth-true .unauthenticated,
.auth-false .authenticated {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Sign-Up/Login Form</title>
<!-- Bootstrap -->
<link href='https://fonts.googleapis.com/css?family=Titillium+Web:400,300,600' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="css/font-awesome-4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/captcha.css">
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body onLoad="ChangeCaptcha()" class="auth-false">
<nav class="navbar navbar-default" style="background-color: #6c757d; min-height: 50px">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" style="color: aliceblue; font-size: 25px" href="#">demo</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right" >
<!-- <li class="active" >What We Do <span class="sr-only">(current)</span></li> -->
<li>menu1</li>
<li>menu2 </li>
<li>menu3</li>
<li>menu4</li>
<!-- <li><button type="button" class="btn navbar-btn userAuth unauthenticated" style="color: #4F5459; font-size: 18px; font-weight: 600; background-color: #ffffff00; outline: 0; box-shadow: none!important;" data-toggle="modal" data-target="#registerModal">Register</button></li> -->
<li><button type="button" class="btn navbar-btn userAuth unauthenticated" style="color: #4F5459; font-size: 18px; font-weight: 600; background-color: #ffffff00; outline: 0; box-shadow: none!important;" data-toggle="modal" data-target="#loginModal">Login</button></li>
<!-- <li></li> -->
<!-- <li><span class="userAuth authenticated user-info"><img src="./user.svg" alt="User" class="rounded-circle"></span></li> -->
<!-- <div class="userAuth authenticated pull-right">
<span class="user-info">
<img src="./user.svg" alt="User" class="rounded-circle">
</span>
<button type="button" class="btn btn-success" id="logout">Logout</button>
</div> -->
<!-- <li><button type="button" class="btn navbar-btn userAuth authenticated" id="logout" style="color: #4F5459; font-size: 18px; font-weight: 600; background-color: #ffffff00; outline: 0; box-shadow: none!important;">Logout</button></li> -->
<button class="btn navbar-btn userAuth unauthenticated" style="background-color: #71D72C; color: #4F5459; font-size: 18px;">Free Trail</button>
<li class="dropdown">
<ul class="dropdown-menu">
<li><a href="#" role="button" class="btn userAuth authenticated" id="Account" style="color: #4F5459; font-size: 18px; text-align: left;" >Account</a></li>
<li><a href="#" role="button" class="btn userAuth authenticated" id="Scheduler" style="color: #4F5459; font-size: 18px; text-align: left;" >payment</a></li>
<li><a href="#" role="button" class="btn userAuth authenticated" id="logout" style="color: #4F5459; font-size: 18px; text-align: left;" >Logout</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<main class="authenticated">
<center>
<h1>welcome to cloud thrifty</h1>
</center>
<div id="contacts"></div>
</main>
<div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="Register" aria-hidden="true" >
<div class="modal-dialog">
<div class="modal-content">
<form id="registerForm" method="POST">
<div class="modal-header">
<h4 class="modal-title" id="registerModalLabel">Register</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="recipient-name" class="control-label">First Name:</label>
<input type="text" class="form-control" id="registerFirstName"required>
</div>
<div class="form-group">
<label for="recipient-name" class="control-label">Last Name:</label>
<input type="text" class="form-control" id="registerLastName"required>
</div>
<div class="form-group">
<label for="recipient-name" class="control-label">Email:</label>
<input type="text" class="form-control" id="registerEmail"required>
</div>
<div class="form-group">
<label for="message-text" class="control-label">Password:</label>
<input type="password" class="form-control" id="registerPassword"required>
</div>
<div class="form-group">
<label for="message-text" class="control-label">Confirm Password:</label>
<input type="password" class="form-control" id="registerConfirmPassword"required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn pull-left" data-toggle="modal" data-target="#loginModal" data-dismiss="modal" style="background-color: #71D72C; border: 0px; color:#fff;">Login</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" id="doRegister" style="background-color: #71D72C; border: 0px">Register</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="Login" aria-hidden="true" >
<div class="modal-dialog">
<div class="modal-content">
<form id="loginForm" method="POST">
<div class="modal-header">
<h4 class="modal-title" id="loginModalLabel">Login</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="recipient-name" class="control-label">Email:</label>
<input type="text" class="form-control" id="loginEmail"required>
</div>
<div class="form-group">
<label for="message-text" class="control-label">Password:</label>
<input type="password" class="form-control" id="loginPassword"required>
</div>
<div class="form-group">
<button class="btn pull-right" style="background-color: #ffffff00; color: #4F5459; font-size: 14px; text-align: left">Forgot password?</button><br>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary pull-left" data-toggle="modal" data-target="#registerModal" data-dismiss="modal" style="background-color: #71D72C; border: 0px;color:#fff;">Register Now</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" id="doLogin" style="background-color: #71D72C; border: 0px" >Login</button>
</div>
</form>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<!-- Firebase App is always required and must be first -->
<!-- <script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-app.js"></script> -->
<!-- Add additional services that you want to use -->
<script src="https://www.gstatic.com/firebasejs/4.3.1/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.8.4/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-messaging.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-functions.js"></script>
<!-- Comment out (or don't include) services that you don't want to use -->
<!-- <script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-storage.js"></script> -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
<!-- <script src="js/index.js"></script> -->
<!-- <script src="js/login.js"></script> -->
<!-- <script src="js/captcha.js"></script> -->
<script src="js/script.js"></script>
</body>
</html>
Every time the user's authentication state changes (i.e. they log in or out), you do:
$('.user-info').append('<span class="user-name">'+name+'<span class="caret"></span></span>');
So you're appending their new state to the existing contents of the .user-info element.
To replace the existing value, use .html instead of .append:
$('.user-info').html('<span class="user-name">'+name+'<span class="caret"></span></span>');

How to Print the Particular bootstrap Div

I would like to print a bootstrap div.
It is properly displayed in web browser but when I click on the print button then at print preview, the elements are floating and are not properly displayed.
what should I do to solve this problem ?
Div which I want to print with following this style
What I get the output at printing time which I dont want see on school name at the top
Button which call the print function:
<button class="btn btn-default" onclick="printDiv('printableArea')"><i class="fa fa-print" aria-hidden="true" style=" font-size: 17px;"> Print</i></button>
Print Function:
function printDiv(divName) {
var printContents = document.getElementById(divName).innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
}
Div which i Want to print
<div class="container right-container col-md-6" id="printableArea" style="display:block;">
<span id="link7">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<h3 id="school_title"><?php echo "$school_name";?> </h3>
<p><p>
<p style="font-size: 1.1em;" id="exam_title">Annual Examination [ 2015-2016 ] <p>
<div class="row">
<div class="col-md-4">
<div class="header-time-date-marks">
<span id="exam_time">Time: 12 AM - 2 PM</span>
<span id="exam_date">Date: 30/12/2016</span>
</div>
</div>
<div class="col-md-8 header-time-date-marks" style="text-align: right;padding-right: 36px;">
<span id="exam_marks">100 Marks</span>
</div>
</div>
</div>
</div>
<hr / id="line" style="margin-top: 13px;">
<div class="row q-question-type-style" id='question_section'>
</div>
</span>
</div>
Check this solution: It is working. The <div> is able to display for print.
Place your <script>-tag above the <html>-tag:
<script>
<html>
https://jsfiddle.net/6cz5br7m/
It's working, just try it on your Editor.
<!-- Your Jquery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!-- Another Jquery version, which will be compatible with PrintThis.js -->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous">
</script>
<!-- CDN/Reference To the pluggin PrintThis.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/printThis/1.15.0/printThis.js"
integrity="sha512-Fd3EQng6gZYBGzHbKd52pV76dXZZravPY7lxfg01nPx5mdekqS8kX4o1NfTtWiHqQyKhEGaReSf4BrtfKc+D5w=="
crossorigin="anonymous"></script>
<script type="text/javascript">
// important : to avoid conflict between the two version of Jquery
var j = jQuery.noConflict(true);
// define a function that you can call as an EventListener or whatever you want ...
function Print_Specific_Element() {
// the element's id must be unique ..
// you can't print multiple element, but can put them all in one div and give it an id, then you will be able to print them !
// use the 'j' alias to call PrintThis, with its compatible version of jquery
j('#specificElement').printThis({
importCSS: true, // to import the page css
importStyle: true, // to import <style>css here will be imported !</style> the stylesheets (bootstrap included !)
loadCSS: true, // to import style="The css writed Here will be imported !"
canvas: true // only if you Have image/Charts ...
});
}
$("#printBtn").click(Print_Specific_Element);
</script>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- It's very important to include the attribute : media='all'-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" media='all'
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<style>
#media print {
#page {
/* To give the user the possibility to choise between landscape and portrait printing format */
size: auto;
/* setting custom margin, so the date and the url can be displayed */
margin: 40px 10px 35px;
}
/* Here you can give a custom styling which will be applied only while printing */
a,
button#printBtn {
display: none;
}
}
</style>
</head>
<body>
<div class="container" id="Page">
<div>
this Element will not be printed
</div>
<div id="specificElement" class="bg-primary m-2 p-2 text-center rounded" style="border: 2px solid black;">
<div class="jumbotron">
<h1 class="display-3">
My custom content which I want to print
</h1>
<p class="lead">Another element</p>
<hr class="my-2">
<p>Nothing ... just another element </p>
<button id="printBtn" class="btn btn-success btn-sm shadow">
CLick Me !
<br>
(Dont worry I will not be printed)
</button>
</div>
</div>
</div>
</body>
</html>
Call this function: PrintElem('printableArea')
function PrintElem(elem){
var mywindow = window.open('', 'PRINT', 'height=400,width=600');
var css = "";
var myStylesLocation = "${pageContext.request.contextPath}/ui/css/bootstrap.min.css";
$.ajax({
url: myStylesLocation,
type: "POST",
async: false
}).done(function(data){
css += data;
})
mywindow.document.write('<html><head><title></title>');
mywindow.document.write('<style type="text/css">'+css+' </style>');
// mywindow.document.write('<link rel="stylesheet" href="${pageContext.request.contextPath}/ui/css/bootstrap.min.css" type="text/css" media="print"/>');
mywindow.document.write('</head><body >');
mywindow.document.write('<h1>' + document.title + '</h1>');
mywindow.document.write(document.getElementById(elem).innerHTML);
mywindow.document.write('</body></html>');
mywindow.document.close(); // necessary for IE >= 10
mywindow.focus(); // necessary for IE >= 10*/
mywindow.print();
mywindow.close();
return true;
}
You can try #media print in css.
Like bellow
In css
#media print
{
p.bodyText {font-family:georgia, times, serif;}
.noprint
{
display:none
}
}
In Html
<div class="noprint">
I dont want it on print
</div>
<br><br>
<div>
Prrintable Area
</div>
Fiddle
I was able to look for the section that was undesirably appearing in the print of the modal, and just hiding it, while using your print function:
print() {
let mainLayout = document.querySelector('app-main-layout') as HTMLDivElement;
mainLayout.style.display = 'none';
window.print();
mainLayout.style.display = 'unset';
}
And, make the buttons of my modal go away, by using this css:
#media print {
button.close {display:none !important;}
}
you just need to link your js script properly
<!DOCTYPE html>
<html>
<body>
<div class="container right-container col-md-6" id="printableArea" style="display:block;">
<span id="link7">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<h3 id="school_title"><?php echo "$school_name";?> </h3>
<p><p>
<p style="font-size: 1.1em;" id="exam_title">Annual Examination [ 2015-2016 ] <p>
<div class="row">
<div class="col-md-4">
<div class="header-time-date-marks">
<span id="exam_time">Time: 12 AM - 2 PM</span>
<span id="exam_date">Date: 30/12/2016</span>
</div>
</div>
<div class="col-md-8 header-time-date-marks" style="text-align: right;padding-right: 36px;">
<span id="exam_marks">100 Marks</span>
</div>
</div>
</div>
</div>
<hr / id="line" style="margin-top: 13px;">
<div class="row q-question-type-style" id='question_section'>
</div>
</span>
</div>
<div> <h1>
asdads
</h1>
</div>
<button class="btn btn-default" onclick="printDiv('printableArea')"><i class="fa fa-print" aria-hidden="true" style=" font-size: 17px;"> Print</i></button>
<script>
function printDiv(divName) {
var printContents = document.getElementById(divName).innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
}
</script>
</body>
</html>

Animate a Bootstrap progressbar from 0 to 100%

I'm using Twitter Bootstrap to build my web page.
I have this HTML code:
<div class="btn-group">
<button type="button" class="btn btn-success">Connect</button>
<button type="button" class="btn btn-success dropdown-data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li> Connect 1</li>
<li role="separator" class="divider"></li>
<li> Connect 2</li>
</ul>
</div>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
</div>
<div class="alert alert-success" role="alert">Well done! You successfully connected. Next</div>
I want to animate the progress bar from 0 to 100% when user push the connect button or push the dropdown button (one of two) and when the progressbar reach 100% the script show the alert previously hidden.
This is all it takes to create an animated progress bar :
var $progressBar = $('.progress-bar').css('width', '80%');
This particular code will animate the progress bar from the current value to a value of 80%.
A demo
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
setTimeout(function() {
$progressBar.css('width', '10%');
setTimeout(function() {
$progressBar.css('width', '30%');
setTimeout(function() {
$progressBar.css('width', '100%');
setTimeout(function() {
$progress.css('display', 'none');
$alert.css('display', 'block');
}, 500); // WAIT 5 milliseconds
}, 2000); // WAIT 2 seconds
}, 1000); // WAIT 1 seconds
}, 1000); // WAIT 1 second
.progress, .alert {
margin: 15px;
}
.alert {
display: none;
}
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
</div>
<div class="alert alert-success" role="alert">Well done! You successfully connected. Next</div>
(see also this Fiddle)
In bootstrap v4 the progress bar animation is not by default anymore.
You can add transition-duration to the progress bar element to slow down the transition from 0 to the new width.
<div class="progress-bar progress-bar-animated" role="progressbar" style="transition-duration:300ms;"></div>
Try this code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example of Bootstrap 3 Progress Bar</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<style type="text/css">
.bs-example{
margin: 20px;
}
</style>
</head>
<body>
<div class="bs-example">
<h2>Task Progress</h2>
<div class="progress">
<div class="progress-bar" id="bar">
<span class="sr-only">60% Complete</span>
</div>
</div>
<script type="text/javascript">
var i = 0;
var progressBar = $("#bar");
function countNumbers(){
if(i < 100){
i = i + 1;
progressBar.css("width", i + "%");
}
// Wait for sometime before running this script again
setTimeout("countNumbers()", 500);
}
countNumbers();
</script>
</div>
</body>
</html>
Taken this example from:
http://www.tutorialrepublic.com/twitter-bootstrap-tutorial/bootstrap-progress-bars.php
http://www.tutorialrepublic.com/html-reference/html5-progress-tag.php
The bootstrap progress bar is animated by default. When you set the progress value to a new value it will cause the the bar to animate. You just need to set the value:
var bar = $(".progress-bar");
bar.attr("aria-valuenow", newValue);
bar.css("width", newValue + "%");
I know this was old enough.
But try code below, it should help you to animate more than one progress bar (if you happen to use more than one within a page).
Everytime you add progress bar, simply add another execProg() with desired width and its respective id
//jQuery for progress bar animating START
function execProg(num, id) {
/* num --> percentage of width
* id --> id of progress bar
*/
var progressBar = $(id);
for (var i = 0; i < num; i++) {
progressBar.css("width", i + "%");
}
}
//The first bar set to 65%
execProg(65, "#barOne");
//The second bar set to 100%
execProg(100, "#barTwo");
//jQuery for progress bar animating END
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="progress" id="setProg">
<div class="progress-bar align-middle" id="barOne">
<p>Some Text Here</p>
</div>
</div>
<div class="m-3"></div>
<div class="progress" id="setProg">
<div class="progress-bar" id="barTwo">
<span class="sr-only">60% Complete</span>
</div>
</div>

Dropzone.js How to use TR or TBODY as preview Template?

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>

Categories