7 changed files with 293 additions and 17 deletions
@ -0,0 +1,191 @@ |
|||
/* rophako cms |
|||
----------- |
|||
HTML5 multi-upload script for the photo albums. |
|||
*/ |
|||
|
|||
function RophakoUpload() { |
|||
var self = this; |
|||
|
|||
// Constants
|
|||
this.MAX_UPLOAD_FILE_SIZE = 1024*1024; // 1 MB
|
|||
this.UPLOAD_URL = "/photos/upload"; |
|||
this.NEXT_URL = "/files/"; |
|||
|
|||
// List of pending files to handle when the Upload button is finally clicked.
|
|||
this.PENDING_FILES = []; |
|||
|
|||
this.ready = function() { |
|||
// Set up the drag/drop zone.
|
|||
self.initDropbox(); |
|||
|
|||
// Set up the handler for the file input box.
|
|||
$("#file-picker").on("change", function() { |
|||
self.handleFiles(this.files); |
|||
}); |
|||
|
|||
// Handle the submit button.
|
|||
$("#upload-button").on("click", function(e) { |
|||
// If the user has JS disabled, none of this code is running but the
|
|||
// file multi-upload input box should still work. In this case they'll
|
|||
// just POST to the upload endpoint directly. However, with JS we'll do
|
|||
// the POST using ajax and then redirect them ourself when done.
|
|||
e.preventDefault(); |
|||
self.doUpload(); |
|||
}); |
|||
}; |
|||
|
|||
this.doUpload = function() { |
|||
$("#upload-progress").show(); |
|||
var $progressBar = $("#upload-progress-bar"); |
|||
|
|||
// Gray out the form.
|
|||
$("#upload-button").attr("disabled", "disabled"); |
|||
|
|||
// Initialize the progress bar.
|
|||
$progressBar.css({"width": "0%"}); |
|||
|
|||
// Collect the form data.
|
|||
fd = self.collectFormData(); |
|||
|
|||
// Attach the files.
|
|||
for (var i = 0, ie = self.PENDING_FILES.length; i < ie; i++) { |
|||
// Collect the other form data.
|
|||
fd.append("file", self.PENDING_FILES[i]); |
|||
} |
|||
|
|||
// Inform the back-end that we're doing this over ajax.
|
|||
fd.append("__ajax", "true"); |
|||
|
|||
var xhr = $.ajax({ |
|||
xhr: function() { |
|||
var xhrobj = $.ajaxSettings.xhr(); |
|||
if (xhrobj.upload) { |
|||
xhrobj.upload.addEventListener("progress", function(event) { |
|||
var percent = 0; |
|||
var position = event.loaded || event.position; |
|||
var total = event.total; |
|||
if (event.lengthComputable) { |
|||
percent = Math.ceil(position / total * 100); |
|||
} |
|||
|
|||
// Set the progress bar.
|
|||
$progressBar.css({"width": percent + "%"}); |
|||
$progressBar.text(percent + "%"); |
|||
}, false) |
|||
} |
|||
return xhrobj; |
|||
}, |
|||
url: self.UPLOAD_URL, |
|||
method: "POST", |
|||
contentType: false, //"multipart/form-data",
|
|||
processData: false, |
|||
dataType: "json", |
|||
cache: false, |
|||
data: fd, |
|||
success: function(data) { |
|||
console.log(data); |
|||
$progressBar.css({"width": "100%"}); |
|||
|
|||
// How'd it go?
|
|||
if (data.status === "error") { |
|||
// Uh-oh.
|
|||
window.alert(data.msg); |
|||
$("#upload-button").removeAttr("disabled"); |
|||
return; |
|||
} |
|||
else { |
|||
// Ok!
|
|||
window.location = data.msg; |
|||
} |
|||
}, |
|||
}); |
|||
}; |
|||
|
|||
|
|||
this.collectFormData = function() { |
|||
// Go through all the form fields and collect their names/values.
|
|||
var fd = new FormData(); |
|||
|
|||
$("#upload-form :input").each(function() { |
|||
var $this = $(this); |
|||
var name = $this.attr("name"); |
|||
var type = $this.attr("type") || ""; |
|||
var value = $this.val(); |
|||
|
|||
// No name = no care.
|
|||
if (name === undefined) { |
|||
return; |
|||
} |
|||
|
|||
// Skip the file upload box for now.
|
|||
if (type === "file") { |
|||
return; |
|||
} |
|||
|
|||
// Checkboxes? Only add their value if they're checked.
|
|||
if (type === "checkbox" || type === "radio") { |
|||
if (!$this.is(":checked")) { |
|||
return; |
|||
} |
|||
} |
|||
|
|||
fd.append(name, value); |
|||
}); |
|||
|
|||
return fd; |
|||
}; |
|||
|
|||
|
|||
this.handleFiles = function(files) { |
|||
// Add them to the pending files list.
|
|||
for (var i = 0, ie = files.length; i < ie; i++) { |
|||
self.PENDING_FILES.push(files[i]); |
|||
} |
|||
}; |
|||
|
|||
|
|||
this.initDropbox = function() { |
|||
var $dropbox = $("#dropbox"); |
|||
|
|||
// On drag enter...
|
|||
$dropbox.on("dragenter", function(e) { |
|||
e.stopPropagation(); |
|||
e.preventDefault(); |
|||
$(this).addClass("active"); |
|||
}); |
|||
|
|||
// On drag over...
|
|||
$dropbox.on("dragover", function(e) { |
|||
e.stopPropagation(); |
|||
e.preventDefault(); |
|||
}); |
|||
|
|||
// On drop...
|
|||
$dropbox.on("drop", function(e) { |
|||
e.preventDefault(); |
|||
$(this).removeClass("active"); |
|||
|
|||
// Get the files.
|
|||
var files = e.originalEvent.dataTransfer.files; |
|||
self.handleFiles(files); |
|||
|
|||
// Update the display to acknowledge the number of pending files.
|
|||
$dropbox.text(self.PENDING_FILES.length + " files ready for upload!"); |
|||
}); |
|||
|
|||
// If the files are dropped outside of the drop zone, the browser will
|
|||
// redirect to show the files in the window. To avoid that we can prevent
|
|||
// the 'drop' event on the document.
|
|||
function stopDefault(e) { |
|||
e.stopPropagation(); |
|||
e.preventDefault(); |
|||
} |
|||
$(document).on("dragenter", stopDefault); |
|||
$(document).on("dragover", stopDefault); |
|||
$(document).on("drop", stopDefault); |
|||
}; |
|||
}; |
|||
|
|||
$(document).ready(function() { |
|||
new RophakoUpload().ready(); |
|||
}); |
Loading…
Reference in new issue