I\'m trying to add a \'percentage completed so far\' progress bar to avatar uploads in BuddyPress. The aim is to stop users navigating away from the page before the upload is co
I'm not familiar with BuddyPress, but all upload handlers (including the HTML5 XHR one that androbin outlined) will have a file progress hook point that you can bind to.
I've used uploadify, uploadifive and swfupload, and they can all interact with the same progress function handler in order to acheive the same progress bar result.
// SWFUpload
$elem.bind('uploadProgress', function(event, file, bytesLoaded) { fnProgress(file, bytesLoaded); })
// Uploadify
$elem.uploadify({ onUploadProgress: function (file, bytesUploaded, bytesTotal, totalBytesUploaded, totalBytesTotal) { fnProgress(file, bytesUploaded); });
// Uploadfive
$elem.uploadifive({ onProgress: function(file, e) { fn.onProgress(file, e.loaded); });
Uploadifive, being an HTML5 based uploader, simply binds to the XHR 'progress' event, so all these properties will be available to any HTML5 uploader.
As for the actual progress bar code..
HTML:
<div class='progressWrapper' style='float: left; width: 100%'>
<div class='progress' style='float: left; width: 0%; color: red'></div>
<div class='progressText' style='float: left;></div>
</div>
JS:
var fnProgress = function(file, bytes) {
var percentage = (bytesLoaded / file.size) * 100;
// Update DOM
$('.progress').css({ 'width': percentage + '%' });
$('.progressText').html(Math.round(percentage + "%");
}
I think that before you worry about the client-side of things you should be aware of the server-side requirements to actually be able to accomplish this.
For PHP you need to have the session.upload_progress enabled unless the wp_handle_upload() function uses something different, so I'm here just guessing, but chances are they do use the regular PHP session stuff hence it needs to be enabled.
If you look at the comments for the given link many users say that progress state does not work under certain environments such as PHP on FastCGI which is what you'll get in shared hosting environments most of the time.
Now many people here are telling you to use the XHR uploader but the problem is that they are giving you an example of a custom upload.php script or something like that to send the data, but you are using a wordpress plugin which you don't control (kinda)
So considering that the wp_handle_upload() does not actually works in an AJAX way then you would have to hook an event when the file upload form submit button is clicked and set a timer in JS which calls some URL where you pass the form data like an ID, and then query the session with that ID to check the progress of the file:
$_SESSION["upload_id"]["content_length"]
$_SESSION["upload_id"]["bytes_processed"]
With that data you can calculate how much has been transfered. You could set the JS timer to be called like each second but if the files they are uploading are not very large (say, larger than 1mb) and they have a good connection then there won't be much progress to be notified.
Check this link for a step by step example on how to work with this session upload data.
You need to inject the progress bar.
I think the only way is to over-ride the function bp_core_avatar_handle_upload using the filter hook apply_filters( 'bp_core_pre_avatar_handle_upload' etc. )
You'll end up duplicating most of the function but you should be able to add your progress bar code.
If you get this working, you should submit it as an enhancement ticket; it's a good idea.
You should use an XHR object. I don't now if it helps you, but I have a simple XHR uploader written.
HTML:
<form id="uploader" enctype="multipart/form-data" action="uploadimage.php" method="post">
<input type="file" id="file" name="file[]" multiple="multiple" accept="image/jpeg" /><br/>
<input type="submit" value="Upload" />
<div class="list" style="background-color:#000;color:#FFF;padding:5px;display:none;border-radius:5px;">
</div>
</form>
JS:
$("#uploader").submit(function(){
$('#uploader .list').fadeIn(100).css("width","0px");
var data = new FormData();
// if you want to append any other data: data.append("ID","");
$.each($('#file')[0].files, function(i, file) {
data.append('file-'+i, file);
});
$.ajax({
url: 'uploadimage.php',
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
xhr: function() { // custom xhr
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // check if upload property exists
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
}
return myXhr;
},
success: function(data2){
$('#uploader .list').css({
"width":"200px",
"text-align":"center",
"margin":"10px 0 10px 0"
}).html("DONE!").delay(2000).fadeOut(500);
if (data2 == "ERROR_FILESIZE"){
return alert("Choose another file");
}
else{ /*change location*/ }
});
return false;
});
In this case I uploaded the file with uploadimage.php
and if it printed: "ERROR_FILESIZE" then it alerted the error.