Progress Bar in Modal not updating - javascript

I have created a PHP upload class that takes a file as input and copies it to the server, this side of the application works fine. My issue that I am having is showing the progress bar updating within a bootstrap modal. The modal shows and I can see the progress bar within the Modal I just don't see the progress bar updating.
I have done the JS code and I have tested that this works, by taking the progress bar HTML out from the modal and placing it on the upload form page and this works fine.
my theory was that maybe the modal is causing the JS to lose context?
$("form").submit(function() {
//$("#loadingModal").modal("show");
$form = $(this);
uploadVideo($form);
});
function uploadVideo($form){
var formdata = new FormData($form[0]); //formelement
var ajax= new XMLHttpRequest();
ajax.upload.addEventListener("progress", function(event){
var percent = (event.loaded /event.total) * 100;
$form.find('.progress-bar').width(percent+'%');
//console.log(percent);
});
//progress completed load event
ajax.addEventListener("load", function(event){
$form.find('.progress-bar');
});
ajax.open("POST", "processing.php");
ajax.send(formdata);
}

If anyone is interested I have resolved this in the end I needed to expose the Modal properties so I added this:
var $el = $("#loadingModal");
I was then able to update the code as follows:
ajax.upload.addEventListener("progress", function(event){
var percent = (event.loaded /event.total) * 100;
$el.find('.progress-bar').width(percent+'%');
//console.log(percent);
});
//progress completed load event
ajax.addEventListener("load", function(event){
$el.find('.progress-bar');
});

Related

How to show a spinner while making an HTTP request (Appcelerator)

Currently, I am trying to show a spinner while making an HTTP request that will end when the call completes. I have built several different spinners but all stop animation the second the call begins.
var spinnerArray = [];
for (var i = 0; i < 20; i++) {
spinnerArray.push('/images/preloaderGif/preloader'+ ("0" + i).slice(-2) + '.gif');
}
$.spinner.images = spinnerArray;
$.spinner.duration = "200";
$.spinner.repeatCount = "0";
spin();
function spin(){
$.spinner.start();
callHTTP() //Prewritten function
Ti.App.addEventListener('callEnd', function(e){
$.spinner.stop();
});
}
This results in the spinner never appearing. Taking the call out or nesting it within a timeout causes the spinner to spin infinitely, or until the timeout ends.
Is there a way to have the spinner continue to spin through the call?
Actually, there's a far better & super easy way to show an indicator. Just follow below steps.
Download this widget Loading Indicator Widget & add it to your project in app->widgets folder. Create widget folder if it doesn't exist.
Add this line "nl.fokkezb.loading" : "*" into your app->config.json file within dependencies dictionary as shown in below screenshot.
Add this line Alloy.Globals.loading = Alloy.createWidget("nl.fokkezb.loading"); in your alloy.js file
Finally, you can use this code to show/hide indicator properly while calling HTTP requests.
function callHTTP() {
if (!Ti.Network.online) {
return;
}
Alloy.Globals.loading.show();
var xhr = Ti.Network.createHTTPClient({
onerror : function(e) {
Alloy.Globals.loading.hide();
},
onload : function(e) {
Alloy.Globals.loading.hide();
// run your additional code here
},
});
xhr.open("GET", url);
xhr.send();
}
callHTTP();
Using this widget, you won't need to write long, error-prone codes for different projects. Just add this widget & you can show/hide loading indicator with just 2 lines of code.
Remember one thing that XHR error/success callbacks are the only places where you can write code to hide the indicators as you can never be sure when the HTTP request will complete.
You could use an ActivityIndicator : http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.ActivityIndicator
$.activityIndicator.show();
var xhr = Ti.Network.createHTTPClient({
onerror : function(e) {
// code
$.activityIndicator.hide();
},
onload : function(e) {
// code
$.activityIndicator.hide();
},
});
xhr.open("GET", url);
xhr.send();

Nonsensical values of loaded and total in AJAX file upload

I am trying to build a progress bar for multiple files drag and drop upload by combining code from tutorial on multiple files drag and drop uploading and tutorial on progress bar uploading.
Javascript part is:
var dropzone = document.getElementById("dropzone");
function updateProgress(e){
document.getElementById("progress").innerHTML = e.loaded + " of " + e.total;
}
function upload(files){
var formData = new FormData(),
xhr = new XMLHttpRequest(),
x;
for(x = 0; x < files.length; x++){
formData.append("file[]", files[x]);
}
xhr.addEventListener("progress", updateProgress, false);
xhr.open("post", "upload.php");
xhr.send(formData);
}
dropzone.ondrop = function(e){
e.preventDefault();
this.className = "dropzone";
upload(e.dataTransfer.files);
}
dropzone.ondragover = function(){
this.className = "dropzone dragover";
return false;
}
dropzone.ondragleave = function(){
this.className = "dropzone";
return false;
}
And upload.php is simply:
<?php
if(!empty($_FILES["file"]["name"][0]))
foreach($_FILES["file"]["name"] as $position => $name)
move_uploaded_file($_FILES["file"]["tmp_name"][$position], "uploads/".$name);
?>
For start, before making actual progress bar, I just want to show the number of uploaded and total bytes. However, function updateProgress doesn't get called if upload.php echoes nothing and otherwise (e.g. if I add echo "something";) e.loaded and e.total are small numbers of same value, unrelated to file size.
File upload itself works fine, even with large files (few hundred MBs). With large files, I've noticed that function updateProgress is called only once - after the upload is complete.
Why is this event handling behaving like this and how to fix it?
You are setting a progress handler for download, to set one for upload use
xhr.upload.addEventListener("progress", updateProgress, false);

Ajax upload progress bar using jQuery

So I don't use jQuery for everything, but I do use it for the good stuff such as AJAX, and right now that son of gun is giving me some issues. Below is a code that should change my upload progress bar while of course uploading.
function uploadProgess(){
var info = document.getElementById('infor');
var images = document.getElementsByName('file[]')[0].files;
$.ajax({
beforeSend: function(XMLHttpRequest){
XMLHttpRequest.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
document.getElementById('progress-bar').style.display="block";
var percentComplete = (evt.loaded / evt.total * 100) + '%';
//Do something with upload progress
document.getElementById('progress').style.width = percentComplete;
}
}, false);
},
type: 'POST',
url: "administration.php?mode=styling&part=pics_management",
data:{method:"upload",file:images},
success: function(response) {
info.innerHTML = response;
},
error:function(response){
info.innerHTML = response;
}
}).done(function(){
window.location.href = window.location.href;
});
}
This function is invoked when we click the submit button of the form.
$('#upload_images').click(function(e){
e.preventDefault();
uploadProgess();
});
But i am getting Uncaught TypeError: Illegal invocation jQuery.js:4 not sure what I did to invoke another property or whatever I did that was "illegal" Can someone explain what is wrong in my code?
This worked perfectly for me... Notes are within code for other users
function uploadProgess(){
//cache our "info" popup element
var info = document.getElementById('infor');
//cache our input element
var images = document.getElementsByName('file[]')[0];
//create a new FormData object (HTML5)
var fileData = new FormData();
//append type is upload
fileData.append("type","upload");
//append method is ajax (only allow ajax uploads)
fileData.append("method","ajax");
//get the files from the input element
var files = images.files;
//loop through the files
for(i=0;i<files.length;i++){
//append to the fileData with name of `file[]` and then the files object for each image
fileData.append('file[]',files[i]);
}
//new ajax request
var request = new XMLHttpRequest();
//event listener progress
request.upload.addEventListener('progress',function(event){
if(event.lengthComputable){
//cache the progress bar
var progress = document.getElementById('progress-bar');
//get our percentage
var percent = (Math.round(event.loaded / event.total) * 100) +"%";
//make the progress bar visible
progress.style.display="block";
//recache for the spinning bar inside progress
progress = document.getElementById('progress');
//change it's width to the percentage of upload
progress.style.width = percent;
}
});
//add event for when the progress is done
request.upload.addEventListener('load',function(event){
//cache progress bar
var progress = document.getElementById('progress-bar');
//hide the progress bar
progress.style.display="none";
});
//for errors we'll use the info element but for now console log it
request.upload.addEventListener('error',function(event){
console.log(event);
});
//open the request
request.open("POST","{URL}");
//set the request header for no caching
request.setRequestHeader("Cache-Control","no-cache");
//send the data
request.send(fileData);
}

how to know external js is loaded or not and put percentage loader until that time

I am loading external js using $.getScript(url). Now until the js is loaded I want percentage loader (to show how much js is loaded) to be shown. How am I to do this.
$(document).on('click', 'div#play', function(){
$(this).hide();
$('div#stop').css('display', 'block');
$('div#processing_load').show();
var url = 'https://www.gstatic.com/swiffy/v5.4/runtime.js';
$.getScript(url)
.done(function(){
$('div#processing_load').hide();
$('#swiffycontainer').css('display', 'block');
$('.landing-banner').css('display', 'none');
stage = new swiffy.Stage(document.getElementById('swiffycontainer'), swiffyobject);
stage.start();
stage.setBackground(null);
})
})
Here I want to show the loader before done with percentage.Thanks in advance. Any help/suggestion is welcome.
Instead of getScript(), use ajax(), which is more powerful. It also allows you to parse xhr data to set a loading status, I edited your code (untested):
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest();
xhr.addEventListener("progress", function (evt) {
//check if the length of the requested file is computable (if you generate the requested file using php, you require ob_start(); and ob_end_flush();)
if (evt.lengthComputable) {
//Calculate the percentage completed
var percentComplete = Math.floor((evt.loaded / evt.total) * 100) + '%';
//Do something with download progress
$('div#processing_load').show().html(percentComplete);
}
}, false);
return xhr;
},
url: 'https://www.gstatic.com/swiffy/v5.4/runtime.js',
dataType: 'script',
complete: function(xhr) {
//you can use the xhr object to check for response codes
$('div#processing_load').hide();
$('#swiffycontainer').css('display', 'block');
$('.landing-banner').css('display', 'none');
var stage = new swiffy.Stage(document.getElementById('swiffycontainer'), swiffyobject);
stage.start();
stage.setBackground(null);
}
});
I think you can't do it exactly ( show by progress bar)
Why ? Because we don't know that how long time Loading is finished.
But you can use some tips to show progressbar :
You need to know file size and can calculate the internet speed.
time to load = your file size / your internet speed ;
=> show progress bar when you begin to load .
To calculate the speed you can base on
Connection type (2G, 3G, WiFi, wired ) => get its speed
Calculate speed connection at the load time . You can read more in http://stackoverflow.com/questions/4583395/calculate-speed-using-javascript
Using Navigation Timing API: window.performance.*
Finally, Noways to show exactly with progress bar( That depends on networks).

progress bar for Multiple file upload using Html5

When I use progress event, I can update the progress bar for one uploading request:
function uploadFile(file) {
fileid=md5(file.name);
if {xhr[fileid] ;== undefined} {
xhr[fileid] = new XMLHttpRequest();
xhr[fileid].open('POST',' {% url upload %}', true);
xhr[fileid].setRequestHeader("X-File-Name", file.name);
xhr[fileid].setRequestHeader("X-File-id", fileid);
xhr[fileid].upload.addEventListener('progress', onprogressHandler, false);
xhr[fileid].upload.addEventListener('load',oncompleteHandler,false);
xhr[fileid].send(file);
}
function onprogressHandler(event) {
var percent = event.loaded/event.total*100;
var $target = $(event.target);
console.log(uploadHolder[fileid]);
uploadHolder[fileid].find(".upload-completed").css('width',percent+'%');
console.log('Upload progress: ' + percent + '%');
}
However, when I sent out more than 2 files upload requests at same time, Only the progress bar for the last file will be changed.
How do I determine which file upload request the event is attached to?
Update:
if I declare the fileid as local variable for uploadFile like var fileid, I cannot access fileid in the event handler. Using 'this' in the event handler give me the XMLHttpRequestUpload object.
You should look for "closure" concept for javascript. After that you'll understand the error. And this concept is so important i think, you should learn it :)

Categories

Resources