Below is the code I am using which basically passes multiple files to be uploaded. In the loop each file is resized client side and then uploaded.
I want to execute an ajax call after the loop is finished uploading the photos. The ajax call basically reloads a specific div and refreshes the photos.
How do I prevent the ajax call from executing until the loop has finished.
if (window.File && window.FileReader && window.FileList && window.Blob)
{
var files = document.getElementById('filesToUpload').files;
for(var i = 0; i < files.length; i++)
{
resizeAndUpload(files[i]);
}
// when loop finished, execute ajax call
$.ajax
({
type: "POST",
url: "photos.php",
data: dataString,
success: function(html)
{
$("#photo-body").html(html);
}
});
}
}
function resizeAndUpload(file)
{
var reader = new FileReader();
reader.onloadend = function()
{
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function()
{
var MAX_WIDTH = 382.25;
var MAX_HEIGHT = 258.5;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH)
{
if (tempW > MAX_WIDTH)
{
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
}
else
{
if (tempH > MAX_HEIGHT)
{
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataURL = canvas.toDataURL("image/jpeg");
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(ev)
{
document.getElementById('filesInfo').innerHTML = 'Upload Complete';
};
xhr.open('POST', 'upload-resized-photos.php', true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
var data = 'image=' + dataURL;
xhr.send(data);
}
}
reader.readAsDataURL(file);
}
var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"];
function Validate(oForm)
{
var arrInputs = oForm.getElementsByTagName("input");
for (var i = 0; i < arrInputs.length; i++)
{
var oInput = arrInputs[i];
if (oInput.type == "file")
{
var sFileName = oInput.value;
if (sFileName.length > 0)
{
var blnValid = false;
for (var j = 0; j < _validFileExtensions.length; j++)
{
var sCurExtension = _validFileExtensions[j];
if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase())
{
blnValid = true;
break;
}
}
if (!blnValid)
{
alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
return false;
}
}
}
}
return true;
}
You can wrap the $ajax call in a function, and call the function at the end of the final loop.
(just the top part of your script)
if (window.File && window.FileReader && window.FileList && window.Blob) {
function loopFinished(){
$.ajax
({
type: "POST",
url: "photos.php",
data: dataString,
success: function(html)
{
$("#photo-body").html(html);
}
});
}
var files = document.getElementById('filesToUpload').files;
for(var i = 0; i < files.length; i++)
{
resizeAndUpload(files[i]);
if (files.length+1 == [i]){
loopFinished();
}
}
}
You can use any promise library to do this. Here is example of using jQuery promise
(function ($) {
var files = [1, 2, 3, 4],
allPromises = [];
for (var i = 0; i < files.length; i++) {
var promise = resizeAndUpload(files[i]);
allPromises.push(promise);
}
$.when.apply($, allPromises).done(function () {
makeAjaxCall();
});
function makeAjaxCall() {
console.log('Put Ajax call here');
}
function resizeAndUpload(file) {
var defer = $.Deferred();
//Set timeout simulates your long running process of processing file
setTimeout(function () {
console.log('processing file ' + file);
defer.resolve();
}, 2000);
return defer.promise();
}
})(jQuery);
Here is a jSFiddle http://jsfiddle.net/x6oh471f/2/
One or more of the methods in your resizeAndUpload() function must be happening asynchronously. Which means they'll do their thing in the background while the rest of your javascript is run and they should fire an event when they are complete. You will want to call the ajax method once the last one of these methods has complete and event fired. For example, the fileReader methods are asychronous. Which means you will probably need to do something like:
FileReader.onloadend = function(){
totalFilesLoaded = totalFilesLoaded + 1;
if (totalFilesLoaded == files.length){
//all files have been uploaded, run $ajax
}
}
EDIT: now you have uploaded the rest of your code, try something like this:
window.totalFilesLoaded = 0;
var files = document.getElementById('filesToUpload').files;
window.totalFilesToLoad = files;
if (window.File && window.FileReader && window.FileList && window.Blob)
{
for(var i = 0; i < files.length; i++)
{
resizeAndUpload(files[i]);
}
}
Separate ajax function:
window.runAjax = function(){
$.ajax
({
type: "POST",
url: "photos.php",
data: dataString,
success: function(html)
{
$("#photo-body").html(html);
}
});
}
function resizeAndUpload(file)
{
var reader = new FileReader();
reader.onloadend = function()
{
...
xhr.onreadystatechange = function(ev)
{
document.getElementById('filesInfo').innerHTML = 'Upload Complete';
window.totalFilesLoaded++;
if (window.totalFilesLoaded == window.totalFilesToLoad.length){
window.runAjax()
}
};
...
}
reader.readAsDataURL(file);
}
Related
Recently I want to start a project by piggyback someone's extension. I want to scope one of the image source (local variable, a base64 url) and then photo recognize it on the popup page. I keep getting error "imgb64.replace is not a function" or "imgb64" not defined.
like my title said, I want to scope the local variable in.in.inside a function (from backgound.js )and use it globally (or in popup.js). very new to this, please help guys.
// this is popup.js
chrome.runtime.getBackgroundPage(function(bg) {
bg.capture(window);
});
/// what I did
function img_find() {
var imgs = document.getElementsByTagName("img");
var imgSrcs = [];
for (var i = 0; i < imgs.length; i++) {
imgSrcs.push(imgs[i].src);
}
return imgSrcs;
}
var imgb64 = img_find();
try {
const app = new Clarifai.App({
apiKey: 'mykey'
});
}
catch(err) {
alert("Need a valid API Key!");
throw "Invalid API Key";
}
// Checks for valid image type
function validFile(imageName) {
var lowerImageName = imageName.toLowerCase();
return lowerImageName.search(/jpg|png|bmp|tiff/gi) != -1;
}
var imageDetails = imgb64.replace(/^data:image\/(.*);base64,/, '');
console.log(imageDetails)
app.models.predict("e466caa0619f444ab97497640cefc4dc", {base64:
imageDetails}).then(
function(response) {
// do something with response
},
function(err) {
// there was an error
}
);
/// end what I did
below is background.js, I think what I need is the local var img.src, thats all.
function capture(popup) {
function callOnLoad(func) {
popup.addEventListener("load", func);
if (popup.document.readyState === "complete") {
func();
}
}
crxCS.insert(null, { file: "capture.js" }, function() {
crxCS.callA(null, "get", function(result) {
var scrShot, zm, bufCav, bufCavCtx;
function mkImgList() {
for (var i = 0; i < result.vidShots.length; i++) {
var img = new popup.Image();
img.onload = function() {
this.style.height = this.naturalHeight /
(this.naturalWidth / 400) + "px";
};
if (result.vidShots[i].constructor === String) {
img.src = result.vidShots[i];
} else {
bufCav.width = result.vidShots[i].width * zm;
bufCav.height = result.vidShots[i].height * zm;
bufCavCtx.drawImage(scrShot, -result.vidShots[i].left *
zm, -result.vidShots[i].top * zm);
img.src = bufCav.toDataURL('image/png');
////// maybe clarifai here ?
////end clarifai
}
popup.document.body.appendChild(img);
}
popup.onclick = function(mouseEvent) {
if (mouseEvent.target.tagName === "IMG") {
chrome.downloads.download({ url: mouseEvent.target.src,
saveAs: true, filename: "chrome_video_capture_" + (new Date()).getTime() +
".png" });
}
};
popup.onunload = function(mouseEvent) {
crxCS.callA(null, "rcy");
};
} /// end mkImgList
if (result.needScrShot) {
bufCav = popup.document.createElement("canvas");
bufCavCtx = bufCav.getContext("2d");
chrome.tabs.captureVisibleTab({ format: "png" },
function(dataUrl) {
scrShot = new Image();
scrShot.onload = function() {
chrome.tabs.getZoom(function(zoomFactor) {
zm = zoomFactor;
callOnLoad(function() {
mkImgList(zoomFactor);
});
});
};
scrShot.src = dataUrl;
});
} else if (result.vidShots.length) {
callOnLoad(mkImgList);
} else {
popup.document.body.appendChild(notFound);
}
}); // end crxCS.callA
}); // end crxCS.insert
} // end capture
Please help guys. :)
My project is about saving the cropped image and show it in the view.
in my form when i cropped the image it works, but when i want to change the image so i crop it again and save. it create two rows with same image.
and when i change the image 3 times it create 3 rows with the same image and so on.
there is method called replace() that i have to use but i dont know how to use it.
this is my code
window.addEventListener('DOMContentLoaded', function () {
var avatar = document.getElementById('avatar');
var image = document.getElementById('image');
var input = document.getElementById('input');
var $progress = $('.progress');
var $progressBar = $('.progress-bar');
var $alert = $('.alert');
var $modal = $('#modal');
var cropper;
var title = $('#title');
var description = $('#description');
var arabic_title = $('#arabic_title');
var arabic_description = $('#arabic_description');
$('[data-toggle="tooltip"]').tooltip();
input.addEventListener('change', function (e) {
var files = e.target.files;
var done = function (url) {
input.value = '';
image.src = url;
// $alert.hide();
$modal.modal('show');
};
var reader;
var file;
var url;
if (files && files.length > 0) {
file = files[0];
if (FileReader) {
reader = new FileReader();
reader.onload = function (e) {
done(reader.result);
console.log('ok2');
};
reader.readAsDataURL(file);
console.log('ok3');
}
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1.7,
viewMode: 3,
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
document.getElementById('crop').addEventListener('click', function () {
var initialAvatarURL;
var canvas;
$modal.modal('hide');
if (cropper) {
canvas = cropper.getCroppedCanvas({
width: 400,
height: 400,
});
initialAvatarURL = avatar.src;
avatar.src = canvas.toDataURL();
$progress.show();
$alert.removeClass('alert-success alert-warning');
document.getElementById('save').addEventListener('click', function () {
canvas.toBlob(function (blob) {
var formData = new FormData();
formData.append('avatar', blob);
formData.append('title', title.val());
formData.append('description', description.val());
formData.append('arabic_title', arabic_title.val());
formData.append('arabic_description', arabic_description.val());
if (title.val() !== '' && description.val() !== '' && arabic_title.val() !== '' && arabic_description.val() !== '') {
for (let pair of formData.entries()) {
console.log(pair[0] + ', ' + pair[1]);
}
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax("{{url('admin/services')}}", {
method: 'POST',
data: formData,
processData: false,
contentType: false,
xhr: function () {
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function (e) {
var percent = '0';
var percentage = '0%';
if (e.lengthComputable) {
percent = Math.round((e.loaded / e.total) * 100);
percentage = percent + '%';
$progressBar.width(percentage).attr('aria-valuenow', percent).text(percentage);
}
};
return xhr;
},
success: function (data) {
$alert.show().addClass('alert-success').text('Upload success');
console.log(data);
},
error: function (error) {
avatar.src = initialAvatarURL;
$alert.show().addClass('alert-warning').text('Upload error');
console.log(error);
},
complete: function () {
$progress.hide();
},
});
}
});
});
}
});
});
$service = 'No service';
if (isset($_FILES['img'])) {
$service = Service::create(['title'=>$request->title,
'description'=>$request->description,
'photo'=>$request->img]);
}
return $service;
Try this.
Your Form Should Be
<form action="files/upload" method="post" enctype="multipart/form-data">
<input type="file" name="photo"/>
</form
Your Controller Should Be like
if ($request->hasFile('photo')) {
// move file upload here
}
Trying to overcome the variable deficiencies of Flash's upload-to-server function - particularly not being able to track upload progress when cookies are required - I have decided to create a JavaScript function that does the upload and keeps track of the upload progress events.
Here it is:
window.you_animate = {
objToString: function(obj) {
var res = "{";
for (var str in obj) {
res += str +"=" + obj[str] + ",";
}
res += "}";
return res;
},
upload: function(url, _files, _data, progressCb, successCb, errorCb) {
alert("a,"+url);
var fd = new FormData(),
files = _files || [],
data = _data || [],
i;
alert("b");
for (i in data) {
fd.append(i, data[i]);
}
alert("c");
for (i = 0; i < files.length; i++) {
var file = files[i];
alert(i+"/"+files.length+" file= "+you_animate.objToString(file));
var blob = file.file || new Blob(file.data, {
type: file.type
});
alert("blob= "+you_animate.objToString(blob));
fd.append(file.name, blob);
}
alert("d");
var ajax_opts = {
type: 'POST',
url: url,
data: fd,
headers: {},
dataType: 'json',
contentType: false,
processData: false,
xhr: function() {
alert("1");
var xhr = new window.XMLHttpRequest();
if (xhr.upload) {
xhr.upload.addEventListener('progress', progressCb, false);
}
return xhr;
},
success: successCb || $.noop,
error: errorCb || $.noop
};
alert("2");
$.ajax(ajax_opts);
alert("3");
},
uploadProgress: {},
// => _data = base64 binary
uploadFromFlash: function(url, _files, _data) {
alert("0");
var uploadProcess = {};
var uploadProcessID = "id" + Math.floor(Math.random() * 1000000).toString();
you_animate.uploadProgress[uploadProcessID] = uploadProcess;
// workaround for Flash bug ("[]" in variable name)
for (var str in _data) {
_data["UploadCharacterForm["+str+"]"] = _data[str];
delete _data[str];
}
alert("01");
// base64 -> Blob-friendly stuff
for (i = 0; i < _files.length; i++) {
var file = _files[i];
var binary = atob(file.data);
var array = new Uint8Array(binary.length);
for( var i = 0; i < binary.length; ++i ) { array[i] = binary.charCodeAt(i) }
file.data = [array]; // NOTE : why "[array]" and not "array" ??
}
alert("02");
you_animate.upload(url, _files, _data,
function(progressEvent) {
uploadProcess.progressEvent = progressEvent;
},
function(successEvent) {
uploadProcess.successEvent = successEvent;
uploadProcess = null;
},
function(errorEvent) {
uploadProcess.errorEvent = errorEvent;
uploadProcess = null;
}
);
return uploadProcessID;
},
trackProcessID: function(id) {
return you_animate.uploadProgress[id];
},
destroyProcessID: function(id) {
delete you_animate.uploadProgress[id];
},
uploadForm: function(form, progressCb, successCb, errorCb) {
var $form = $(form),
action = $form.attr('action') + '?json';
var data = $form.serializeArray().reduce(function(prev, curr){
prev[curr.name] = curr.value; return prev;
}, {} );
var $files = $form.find('input[type=file]');
var files = [];
$files.each(function(index, node) {
if (node.files[0]) {
files.push({
name: node.name,
file: node.files[0]
});
}
});
you_animate.upload(action, files, data, progressCb, successCb, errorCb);
}
};
Question 1: the progress event differs between Chrome and Firefox. The first returns loaded & totalSize (among lots of other stuff), while Firefox returns loaded & total!!!
Is there somewhere a specification for the returned progress event?!
Question 2: Internet Explorer 8 crashes right after alert("0") ! Maybe it doesn't like "[ ]" in the following line:
_data["UploadCharacterForm["+str+"]"] = _data[str];
Anything to do about that?
i am developing chrome extension and i want to set the download location for the downloadable files. So i am using chrome.downloads.download API saveAs:true.It is working fine in windows OS but in Mac OS saveAs popup is flashing on the screen and then extension popup and saveAs dialogue is closing before i see them.
Any idea?
My updated code:
manifest.json
{
"name": "Download Selected Links",
"description": "Select links on a page and download them.",
"version": "0.1",
"minimum_chrome_version": "16.0.884",
"permissions": ["downloads", "<all_urls>"],
"background": {
"scripts": ["background.js"]
},
"browser_action": {"default_popup": "popup.html"},
"manifest_version": 2
}
popup.js
var allLinks = [];
var visibleLinks = [];
var filename = [];
var count = 0;
// Display all visible links.
function showLinks() {
var linksTable = document.getElementById('links');
while (linksTable.children.length > 1) {
linksTable.removeChild(linksTable.children[linksTable.children.length - 1])
}
for (var i = 0; i < visibleLinks.length; ++i) {
var row = document.createElement('tr');
var col0 = document.createElement('td');
var col1 = document.createElement('td');
var checkbox = document.createElement('input');
checkbox.checked = true;
checkbox.type = 'checkbox';
checkbox.id = 'check' + i;
col0.appendChild(checkbox);
col1.innerText = visibleLinks[i];
col1.style.whiteSpace = 'nowrap';
col1.onclick = function() {
checkbox.checked = !checkbox.checked;
}
row.appendChild(col0);
row.appendChild(col1);
linksTable.appendChild(row);
}
}
function toggleAll() {
var checked = document.getElementById('toggle_all').checked;
for (var i = 0; i < visibleLinks.length; ++i) {
document.getElementById('check' + i).checked = checked;
}
}
function downloadLinks() {
var urlArray = new Array();
for (var i = 0; i < visibleLinks.length; ++i) {
if (document.getElementById('check' + i).checked) {
urlArray.push(visibleLinks[i]);
}
}
var zip = new JSZip();
downloadFile(urlArray[count], onDownloadComplete, urlArray, zip);
}
// Re-filter allLinks into visibleLinks and reshow visibleLinks.
function filterLinks() {
var filterValue = document.getElementById('filter').value;
if (document.getElementById('regex').checked) {
visibleLinks = allLinks.filter(function(link) {
return link.match(filterValue);
});
} else {
var terms = filterValue.split(' ');
visibleLinks = allLinks.filter(function(link) {
for (var termI = 0; termI < terms.length; ++termI) {
var term = terms[termI];
if (term.length != 0) {
var expected = (term[0] != '-');
if (!expected) {
term = term.substr(1);
if (term.length == 0) {
continue;
}
}
var found = (-1 !== link.indexOf(term));
if (found != expected) {
return false;
}
}
}
return true;
});
}
showLinks();
}
chrome.runtime.onMessage.addListener(function(links) {
for (var index in links) {
allLinks.push(links[index]);
}
allLinks.sort();
visibleLinks = allLinks;
showLinks();
});
window.onload = function() {
document.getElementById('filter').onkeyup = filterLinks;
document.getElementById('regex').onchange = filterLinks;
document.getElementById('toggle_all').onchange = toggleAll;
document.getElementById('downloadButtonId').onclick = downloadLinks;
chrome.windows.getCurrent(function (currentWindow) {
chrome.tabs.query({active: true, windowId: currentWindow.id},
function(activeTabs) {
chrome.tabs.executeScript(
activeTabs[0].id, {file: 'source.js', allFrames: true});
});
});
};
source.js
var links = [].slice.apply(document.getElementsByTagName('a'));
links = links.map(function(element) {
var href = element.href;
var hashIndex = href.indexOf('#');
if (hashIndex >= 0) {
href = href.substr(0, hashIndex);
}
return href;
});
links.sort();
// Remove duplicates and invalid URLs.
var kBadPrefix = 'javascript';
for (var i = 0; i < links.length;) {
if (((i > 0) && (links[i] == links[i - 1])) ||
(links[i] == '') ||
(kBadPrefix == links[i].toLowerCase().substr(0, kBadPrefix.length))) {
links.splice(i, 1);
} else {
++i;
}
}
chrome.runtime.sendMessage(links);
background.js
function downloadFile(url, onSuccess, arrayOfUrl, zip) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (onSuccess) {
onDownloadComplete(xhr.response, arrayOfUrl, zip);
}
}
}
xhr.send(null);
}
function onDownloadComplete(blobData, urls, zip){
if (count < urls.length) {
blobToBase64(blobData, function(binaryData){
// add downloaded file to zip:
var fileName = urls[count].substring(urls[count].lastIndexOf('/')+1);
// zip.file(fileName, binaryData, {base64: true});
zip.file(fileName+".docx", binaryData, {base64: true}); //file"+count+".docx"
if (count < urls.length -1){
count++;
downloadFile(urls[count], onDownloadComplete, urls, zip);
} else {
chrome.runtime.getBackgroundPage(function () {
zipAndSaveFiles(zip);
});
}
});
}
}
function blobToBase64(blob, callback) {
var reader = new FileReader();
reader.onload = function() {
var dataUrl = reader.result;
var base64 = dataUrl.split(',')[1];
callback(base64);
};
reader.readAsDataURL(blob);
}
function zipAndSaveFiles(zip) {
chrome.windows.getLastFocused(function(window) {
var content = zip.generate(zip);
var zipName = 'download.zip';
var dataURL = 'data:application/zip;base64,' + content;
chrome.downloads.download({
url: dataURL,
filename: zipName,
saveAs: true
});
});
}
This is a known bug on MAC for over 3 years now. As a work-around, you can delegate the dialog-opening-zipping-and-downloading action to your background page.
In order to achieve this, you need to make the following modification to your code (organized by file):
popup.html (or whatever you call it)
Remove JSZip (you only need it in the background-page now).
manifest.json
// Replace:
"background": {
"scripts": ["background.js"]
},
// with:
"background": {
"scripts": ["jszip.js(or whatever the name)", "background.js"]
},
background.js
// Replace:
if (onSuccess) {
onDownloadComplete(xhr.response, arrayOfUrl, zip);
}
// with:
if (onSuccess) {
onSuccess(xhr.response, arrayOfUrl, zip);
}
// Replace:
chrome.runtime.getBackgroundPage(function () {
zipAndSaveFiles(zip);
});
// with:
zipAndSaveFiles(zip);
// Add:
var count;
chrome.runtime.onMessage.addListener(function (msg) {
if ((msg.action === 'download') && (msg.urls !== undefined)) {
// You should check that `msg.urls` is a non-empty array...
count = 0;
var zip = new JSZip();
downloadFile(msg.urls[count], onDownloadComplete, msg.urls, zip);
}
}
popup.js
// Replace:
function downloadLinks() {
...
}
// with:
function downloadLinks() {
var urlArray = new Array();
for (var i = 0; i < visibleLinks.length; ++i) {
if (document.getElementById('check' + i).checked) {
urlArray.push(visibleLinks[i]);
}
}
//var zip = new JSZip();
//downloadFile(urlArray[count], onDownloadComplete, urlArray, zip);
chrome.runtime.sendMessage({
action: 'download',
urls: urlArray
});
}
(As I already mentioned, I am only guessing here, since I am not able to reproduce the issue.)
I have done some code to upload multiple files from browser to server, while showing progressbars as well.
XHR2 send calls are asynchronous. The problem is that I want to call some functions after all the XHR2 send calls are finished.
Here is a very simplified snippet of my code:
<input id="upload" multiple="multiple" />
<script>
var files = document.getElementById("upload").files;
for (var i = 0, length = files.length; i < length; i++) {
var file = files[i];
var uploadFunc = function (arg) {
return function () {
processXHR(arg);
};
}(file);
uploadFunc();
}
function processXHR(file) {
var normalizedFileName = getNormalizedName(file.name);
var url = 'upload_file/';
var formData = new FormData();
formData.append("docfile", file);
var xhr = new XMLHttpRequest();
var eventSource = xhr.upload;
eventSource.addEventListener("progress", function (evt) {
var position = evt.position || evt.loaded;
var total = evt.totalSize || evt.total;
console.log('progress_' + normalizedFileName);
console.log(total + ":" + position);
$('#progress_' + normalizedFileName).css('width', (position * 100 / total).toString() + '%');
}, false);
eventSource.addEventListener("loadstart", function (evt) {
console.log('loadstart');
}, false);
eventSource.addEventListener("abort", function (evt) {
console.log('abort');
}, false);
eventSource.addEventListener("error", function (evt) {
console.log('error');
}, false);
eventSource.addEventListener("timeout", function (evt) {
console.log('timeout');
}, false);
xhr.onreadystatechange = function (evt) {
if (xhr.readyState == 4) {
console.log('onreadystatechange: File uploaded.');
}
};
xhr.open('post', url, true);
xhr.send(formData);
}
</script>
Whenever "onreadystatechange: File uploaded." is printed in console, I know that one of the files is done uploading.
But I am not able to write any code that will say "All Files uploaded.".
Thanks for any help.
I am using jquery as well in case some one has a solution using jquery.
Do you know how many calls you are making? If so, at least ajax callback, you check the count. Something like
if (ajaxCallCount === ajaxCallsLength) {
// Do stuff involving post all ajax calls
} else {
ajaxCallCount++;
}
You will need a counter and setInterval method in your case, try this:
<input id="upload" multiple="multiple" />
<script>
var files = document.getElementById("upload").files;
var counter = 0;
for (var i = 0, length = files.length; i < length; i++) {
var file = files[i];
var uploadFunc = function (arg) {
return function () {
processXHR(arg);
};
}(file);
uploadFunc();
}
var interval = setInterval(function() {
if(counter == files.length) {
clearInterval(interval);
console.log("All Files uploaded!");
}
}, 100);
function processXHR(file) {
var normalizedFileName = getNormalizedName(file.name);
var url = 'upload_file/';
var formData = new FormData();
formData.append("docfile", file);
var xhr = new XMLHttpRequest();
var eventSource = xhr.upload;
eventSource.addEventListener("progress", function (evt) {
var position = evt.position || evt.loaded;
var total = evt.totalSize || evt.total;
console.log('progress_' + normalizedFileName);
console.log(total + ":" + position);
$('#progress_' + normalizedFileName).css('width', (position * 100 / total).toString() + '%');
}, false);
eventSource.addEventListener("loadstart", function (evt) {
console.log('loadstart');
}, false);
eventSource.addEventListener("abort", function (evt) {
console.log('abort');
}, false);
eventSource.addEventListener("error", function (evt) {
console.log('error');
}, false);
eventSource.addEventListener("timeout", function (evt) {
console.log('timeout');
}, false);
xhr.onreadystatechange = function (evt) {
if (xhr.readyState == 4) {
counter += 1;
}
};
xhr.open('post', url, true);
xhr.send(formData);
}
</script>