1

I have my code almost functional but the event listener "Progress" isn't firing and so i am unable to track the progress of my upload.

The event listener "Load" is firing and the rest of my code is executing so I'm at a loss. Does anyone have any suggestions?

$("#myForm").submit(function(){
var xhr = new XMLHttpRequest();

//Progress Tracking
xhr.upload.addEventListener("progress", function(e){
    if(e.lengthComputable){
        alert('test');
        var percentage = Math.round((e.loaded * 100) / e.total);
        $("#myProgress").innerHTML(percentage + '%');
        $("#Progress").val(percentage);
    }
}, false);

//Added just to test that something was firing.
xhr.addEventListener("load", function(){alert('load');}, false);
xhr.addEventListener("error", function(){alert('error');}, false);
xhr.addEventListener("abort", function(){alert('abort');}, false);

//Status Tracking
xhr.open(this.method, this.action, true);
xhr.setRequestHeader("X-FILENAME", this.name);
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        $('#myForm')[0].reset();
    }
};

//Submit Data
var fd = new FormData();
fd.append("text", $('#text').val());
fd.append("file", $('#file')[0].files[0]);

xhr.send(fd);
return false;
});
Ryan
  • 57
  • 2
  • 9
  • Try `xhr.upload.onprogress = function() { ... }` instead - [How to get progress when uploading file VIA XMLHttpRequest](http://stackoverflow.com/questions/7409954/how-to-get-progress-when-uploading-file-via-xmlhttprequest) – Andreas Dec 03 '13 at 19:25
  • What browser are you using? – j08691 Dec 03 '13 at 19:32
  • I tried xhr.upload.onprogress but the same result occurred. – Ryan Dec 03 '13 at 20:53

1 Answers1

2

As your using XMLHttpRequest & FormData... so modern browsers (chrome,safari,ie10,ios,android)

here is a very short version of ajax.

function ajax(a,b,e,d,c){//Url,callback,method,formdata or{key:val},placeholder
 c=new XMLHttpRequest;
 c.onload=b;
 c.open(e||'get',a);
 c.send(d||null)
}

usage

ajax('index.html',callback);
// does a get query to index.html and calls the callback onload

ajax('upload.php',callback,'post',new FormData(form));
//posts the whole form to the upload.php and calls the callback onload

now you want the progress events.

addEventListener is good if you want to add multiple eventhandlers but as you just need one progress handler the xhr.onprogess & xhr.upload.onprogress are enough.

so:

function ajax(a,b,e,d,f,g,c){
 c=new XMLHttpRequest;
 !f||(c.upload.onprogress=f);
 !g||(c.onprogress=g);
 c.onload=b;
 c.open(e||'get',a);
 c.send(d||null)
}

in this case we destroy the usability of this previously created function but we can do alot more.

/*
a=url  -  index.php,data.json,script.js
b=callback - function(){console.log(this.response)}
e=method - post,get ?put ?delete
d=formdata or object - new FormData(form) or {key:val}
f=upload progress func - function(){console.log(e.loaded/e.total*100>>0)}
g=download progress func - ""
c=this is just a placeholder - -----
*/

Now regarding your function you just create some short code to do the rest for you:

var form;
function uploadProgress(e){
 console.log(e.lengthComputable?(e.loaded/e.total*100>>0)+'%':'NO SIZE');
}
function uploadThatStuff(){
 ajax('upload.php',finish,'post',new FormData(form),uploadProgress);
}
function finish(){
 console.log('upload finished',this.response);
}
window.onload=function(){
 form=document.getElementsByTagName('form')[0];
 form.onsubmit=uploadThatStuff;
}

just replace yourForm & upload.php ... and add also the 2nd ajax function

if you have some questions just ask

as a test php you could use

<?php
print_r(array($_FILES,$_POST,$_GET));
?>

EDIT

full working example with progress bar

<?php
if($_FILES){
 print_r(array($_FILES,$_POST));
}else{
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Upload</title>
<style>
body>div{
 width:300px;
 height:20px;
 border:1px solid rgba(0,0,0,0.5);
}
body>div>div{
 width:0%;
 height:100%;
 background-color:green;    
}
</style>
<script>
var form,progress,result;
function ajax(a,b,e,d,f,g,c){
 c=new XMLHttpRequest;
 !f||(c.upload.onprogress=f);
 !g||(c.onprogress=g);
 c.onload=b;
 c.open(e||'get',a);
 c.send(d||null)
}
function uploadProgress(e){
 e=e||window.event;
 progress.firstChild.style.width=((e.loaded||e.position)/(e.total||e.totalSize)*100>>0)+'%';
}
function uploadThatStuff(e){
 e=e||window.event;
 e.preventDefault();
 //form.title.value?form.file.files[0]?
 ajax('upload.php',finish,'post',new FormData(form),uploadProgress)
 //:alert('Please add a file'):alert('Please add a title');
}
function finish(e){
 result.textContent=this.response||(e=e||window.event,e.target=e.target||e.srcElement,e.target.response);
}
window.onload=function(){
 form=document.getElementsByTagName('form')[0];
 form.onsubmit=uploadThatStuff;
 progress=document.getElementsByTagName('div')[0];
 result=document.getElementsByTagName('pre')[0];
}
</script>
</head>
<body>
<form>
<input name="title">title<br>
<input type="file" name="file"><br>
<input type="submit" value="Send">
</form>
<div><div></div></div>
<pre></pre>
</body>
</html>
<?php
}
?>

past in a text file and save as upload.php

cocco
  • 16,442
  • 7
  • 62
  • 77
  • I am still digesting your post but this is very informative. thank you for taking the time to answer my question. I'm going to try and get it to work. – Ryan Dec 03 '13 at 21:11
  • Thank you very much, i was having a hard time understanding until you posted the example. I just uploaded your code and ran it. The array is all intact but the styling changes don't take place. I'm assuming the green bar's width increases as the upload progresses but that's not the case when i run it. Is this related to the server I'm working on somehow? – Ryan Dec 03 '13 at 21:42
  • you get e.loaded? & What browser are you using?... add console.log(e.loaded); in the uploadProgress function,the div's don't allow spaces in the html to make it work as i use firstChild. – cocco Dec 03 '13 at 21:48
  • I'm using Firefox 25.0.1, alert(e.loaded); did not pop anything up. I added console.log(e.loaded); as you requested but I'm not sure what that does. – Ryan Dec 03 '13 at 21:57
  • firefox does not properly support xhr2, try replacing this.response with e.target.response... & look for erros in console.. i also think you can't use xhr.onload .. so you need xhr.onreadystatechange – cocco Dec 03 '13 at 21:58
  • Hah, just tested in IE and it works. Is there no solution that works cross browser? PS thank for you help i am learning a ton! – Ryan Dec 03 '13 at 22:00
  • I do see this in firebug ReferenceError: e is not defined (41 out of range 21) after changing e.target.response – Ryan Dec 03 '13 at 22:03
  • e=e||window.event;e.target=e.target||e.srcElement; add this inside uploadProgress & uploadThatStuff on top – cocco Dec 03 '13 at 22:05
  • Same reference error in firebug. Ill update your example with my current code so you can see it. – Ryan Dec 03 '13 at 22:08
  • No console errors, i see the two arrays again but the status bar doesn't change. – Ryan Dec 03 '13 at 22:25
  • is the progressbar green or white?? if it's green it works... just try to upload bigger files or upload it to a remote server to test the animation even with 2-3mb files you don't see an animation if your triyng local – cocco Dec 03 '13 at 22:25
  • No, the inner div is still at 0% width. – Ryan Dec 03 '13 at 22:27
  • replace 'e.loaded/e.total' with '(e.loaded||e.position)/(e.total||e.totalSize)' this? add console.log(e) at the end. – cocco Dec 03 '13 at 22:31
  • I don't see that line, was i supposed to add it? – Ryan Dec 03 '13 at 22:33
  • So weird, same results. no console errors and the two arrays are displayed but the inner div is still at 0% with no green being displayed. – Ryan Dec 03 '13 at 22:39
  • add console.log(e) at the end of the uploadProgress function and serach for loaded,position,total & totalSize and read in the console what you get. – cocco Dec 03 '13 at 22:41
  • I added the line, but are you referring to the browser console or something else? I don't see anything in the browser console for the page we created. – Ryan Dec 03 '13 at 22:49
  • looks like firefox has some problems with the xhr.upload.progress event http://stackoverflow.com/a/10508836/2450730 , use chrome or forgot about the upload progress event... like i said it works on most other big new browsers (mobile & desktop) without tons of other checks like in the latest example – cocco Dec 03 '13 at 22:53
  • I think i would agree with you. I was hoping for Firefox as most of my office uses it and i wanted to event to help validate the user experience but this is more work than its worth i think. I appreciate your effort, if nothing else i learned a lot. – Ryan Dec 03 '13 at 22:56
  • wait.. maybe some last thing can seve us. Test now – cocco Dec 03 '13 at 22:57
  • i forgot to set the events before open() in the ajax function. but that makes no difference.. prolly.. – cocco Dec 03 '13 at 22:59