I am attempting to use XMLHttpRequest to upload files to the server. Here are the steps I would like the code to do:
- List the file in a file list ul
- Upload the file(s) while displaying a progress bar
- When the file is completely uploaded, change the list item for that file to a link without the progress bar. This is where I am having a problem.
Here is the HTML code I am working with:
<h1>Upload Files</h1>
<input type='file' name='doc_upload_field[][]' multiple='multiple' id='doc_upload_field' />
<ul id='filelist'></ul>
Here is the javascript code I am working with:
function transferFailed(evt) {
alert("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
alert("The transfer has been canceled by the user.");
}
var filelist = $('#filelist');//define where the list of files will go
var url = "/";
function handleFileSelect_inputfield(evt) {
var files = evt.target.files; // FileList object
// run through each file individually.
for (var i = 0, f; f = files[i]; i++) {
var li = $("<li><strong>" + f.name + "</strong> (" + f.type +") - " + f.size + " bytes <div class='progress_bar'><div class='percent'> </div></div></li>");
filelist.append(li);//put the file in the filelist
var formData = new FormData();
formData.append(f.name, f);
//upload through xmlhttprequest
var xhr = new XMLHttpRequest();
xhr.upload.li = li;
xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var percentLoaded = Math.round((e.loaded / e.total) * 100);
// Increase the progress bar length.
if (percentLoaded < 100) {
this.li.find(".progress_bar").addClass('loading');
this.li.find(".percent").width(percentLoaded + '%');
}
}
}, false);
xhr.upload.addEventListener("load", function(e) {
//uploading is complete
}, false);
xhr.upload.addEventListener("error", transferFailed, false);
xhr.upload.addEventListener("abort", transferCanceled, false);
xhr.open('POST', url, true);
xhr.responseType = 'text';
xhr.onload = function(e) {
if (this.readyState==4){
if (this.status == 200) {
//console.log(this.response);
console.log("finished=" + li);//returns as an object
//console.log("filename=" + f.name);//error: cannot read property 'name' of undefined
//change the list item. Not working...
this.li.find("li").html("<a href='#'>" + f.name + "</a>");
}
}
};
xhr.send(formData); // multipart/form-data
}
}
document.getElementById('doc_upload_field').addEventListener('change', handleFileSelect_inputfield, false);
Everything seems to be working, 开发者_StackOverflow中文版but when I want to change the list item, li, it is not recognizing it. I am able to change the progress bar length by calling:
this.li.find(".progress_bar").addClass('loading');
this.li.find(".percent").width(percentLoaded + '%');
But when I want to change the list item:
this.li.find("li").html("<a href='#'>" + f.name + "</a>");
It does not work.
Does anyone know why it would find it when changing the progress bar, but not find it after it is uploaded?
The expression
this.li.find("li")
looks for an <li>
element inside the other <li>
element. There isn't one, so nothing happens.
I think that just
this.li.html("<a href='#'>" + f.name + "</a>");
should be what you want. Or you could just do this:
this.li = $("<li><a href='#'>" + f.name + "</a></li>");
edit oops no that won't work because you've stuck it in the DOM already. But the first one should work.
edit — you've also got a closure-related problem (or scope-related; whatever). What you can do is something like what you've already done for the "li" value. Add another property for it to "xhr.upload":
xhr.upload.updated_li = "<a href='#'>" + f.name + "</a>";
Do that right where you set "xhr.updated.li". Then, in the event handler, you can do:
this.li.html(this.updated_li);
精彩评论