123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- function Dropbox(dropbox, url) {
- this.box = dropbox;
- this.url = url;
- this.queue = [];
- this.num_current_uploads = 0;
-
- // Add clickable file picker
- this.picker = document.createElement('input');
- this.picker.setAttribute('type', 'file');
- this.box.appendChild(this.picker);
- // Add progress bar container
- this.uploads = document.createElement('div');
- this.box.parentNode.insertBefore(this.uploads, this.box.nextSibling);
-
- // Optional defaults
- this.max_concurrent = 2; // Queue uploads after n concurrent
- this.max_size = null; // Max size in MB
- this.success = null; // Callback on successful upload, passed the response body
- this.error = null; // Callback on upload failure, passed the error text
- this.mime_types = null; // A regex to match file mime types
-
- var _this = this;
- // Init drag and drop handlers
- this.box.addEventListener("dragenter", function(e) { _this.drag(e, true) }, false);
- this.box.addEventListener("dragleave", function(e) { _this.drag(e, false) }, false);
- this.box.addEventListener("dragover", noop, false);
- this.box.addEventListener("drop", function(e) { _this.drop(e) }, false);
- this.picker.addEventListener("change", function(e) { _this.drop(e) })
- }
-
- Dropbox.prototype.drop = function(e) {
- this.drag(e, false);
- var files = (e.dataTransfer || e.target).files;
- for ( var i=0; i<files.length; i++ )
- this.handle_file(files[i]);
- }
-
- Dropbox.prototype.drag = function(e, active) {
- noop(e);
- this.box.className = active ? this.box.className += ' active' : this.box.className.replace(/ ?active/, '');
- }
-
- Dropbox.prototype.handle_file = function(file) {
- // Bad file type
- if ( this.mime_types && !file.type.match(this.mime_types) ) {
- alertify.error(file.name + ' is not an allowed file type');
- // Too large
- } else if ( this.max_size && (file.size / 1024 / 1024) > this.max_size ) {
- alertify.error(file.name + ' is too large; maximum is ' + this.max_size.toFixed(2) + ' MB');
- } else {
- file.label = this.add_label(file);
- // Enqueue it
- if ( this.max_concurrent > -1 && this.num_current_uploads >= this.max_concurrent )
- this.queue.push(file);
- // Upload it
- else this.process_file(file);
- }
- }
-
- Dropbox.prototype.process_file = function(file) {
- this.num_current_uploads += 1;
- var _this = this;
- var reader = new FileReader();
- reader.onload = function(e) {
- var file_contents = e.target.result.split(',')[1];
- _this.upload_file(file, file_contents);
- }
- reader.readAsDataURL(file);
- }
-
- Dropbox.prototype.upload_file = function(file, file_contents) {
- // Build form
- var data = new FormData();
- data.append('filename', file.name);
- data.append('mimetype', file.type);
- data.append('data', file_contents);
- data.append('size', file.size);
-
- var _this = this;
- var xhr = new XMLHttpRequest();
- // Update progress bar (if available)
- if ( xhr.upload ) xhr.upload.addEventListener('progress', function(e) { _this.handle_upload_progress(e, file.label) }, false)
- xhr.open('POST', this.url);
- xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
- xhr.onreadystatechange = function(e) {
- if ( xhr.readyState === 4 ) {
- // Success
- if (xhr.status === 200) {
- file.label.getElementsByClassName('percent')[0].innerHTML = '100%';
- if ( _this.success ) _this.success(file, xhr.responseText);
- // Error
- } else {
- file.label.getElementsByClassName('percent')[0].innerHTML = 'Error';
- if ( _this.error ) _this.error(file, xhr.statusText, xhr.responseText);
- }
- // Pop next upload off the queue
- _this.num_current_uploads -= 1;
- if ( _this.queue.length > 0 ) _this.process_file(_this.queue.shift())
- // Remove the label in 1 second
- setTimeout(function() { _this.uploads.removeChild(file.label) }, 1000);
- }
- }
- xhr.send(data)
- }
-
- Dropbox.prototype.handle_upload_progress = function(e, label) {
- if ( e.lengthComputable ) {
- var progress = label.getElementsByTagName('progress')[0];
- progress.setAttribute('value', e.loaded);
- progress.setAttribute('max', e.total);
- label.getElementsByClassName('percent')[0].innerHTML = ((e.loaded / e.total) * 100).toFixed(0) + '%';
- }
- }
-
- Dropbox.prototype.add_label = function(file) {
- var size = (file.size / 1024 / 1024).toFixed(2);
- var label = document.createElement('div');
- label.setAttribute('class', 'upload-progress');
- label.innerHTML = '<progress value="0" max="100"></progress> <span class="desc">' + file.name + ' - <span class="percent">0%</span> (' + size + ' MB)</span>';
- this.uploads.insertBefore(label, null);
- return label;
- }
-
- function noop(e) {
- e.stopPropagation();
- e.preventDefault();
- }
|