diff options
Diffstat (limited to 'apps/files/js/file-upload.js')
-rw-r--r-- | apps/files/js/file-upload.js | 790 |
1 files changed, 562 insertions, 228 deletions
diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 56ea384c9e0..0d45623ce65 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -18,83 +18,448 @@ * - TODO music upload button */ -/* global jQuery, oc_requesttoken, humanFileSize, FileList */ +/* global jQuery, humanFileSize */ /** - * Function that will allow us to know if Ajax uploads are supported - * @link https://github.com/New-Bamboo/example-ajax-upload/blob/master/public/index.html - * also see article @link http://blog.new-bamboo.co.uk/2012/01/10/ridiculously-simple-ajax-uploads-with-formdata + * File upload object + * + * @class OC.FileUpload + * @classdesc + * + * Represents a file upload + * + * @param {OC.Uploader} uploader uploader + * @param {Object} data blueimp data */ -function supportAjaxUploadWithProgress() { - return supportFileAPI() && supportAjaxUploadProgressEvents() && supportFormData(); - - // Is the File API supported? - function supportFileAPI() { - var fi = document.createElement('INPUT'); - fi.type = 'file'; - return 'files' in fi; - } +OC.FileUpload = function(uploader, data) { + this.uploader = uploader; + this.data = data; +}; +OC.FileUpload.CONFLICT_MODE_DETECT = 0; +OC.FileUpload.CONFLICT_MODE_OVERWRITE = 1; +OC.FileUpload.CONFLICT_MODE_AUTORENAME = 2; +OC.FileUpload.prototype = { - // Are progress events supported? - function supportAjaxUploadProgressEvents() { - var xhr = new XMLHttpRequest(); - return !! (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload)); - } + /** + * Upload element + * + * @type Object + */ + $uploadEl: null, - // Is FormData supported? - function supportFormData() { - return !! window.FormData; - } -} + /** + * Target folder + * + * @type string + */ + _targetFolder: '', -/** - * Add form data into the given form data - * - * @param {Array|Object} formData form data which can either be an array or an object - * @param {Object} newData key-values to add to the form data - * - * @return updated form data - */ -function addFormData(formData, newData) { - // in IE8, formData is an array instead of object - if (_.isArray(formData)) { - _.each(newData, function(value, key) { - formData.push({name: key, value: value}); + /** + * @type int + */ + _conflictMode: OC.FileUpload.CONFLICT_MODE_DETECT, + + /** + * New name from server after autorename + * + * @type String + */ + _newName: null, + + /** + * Returns the file to be uploaded + * + * @return {File} file + */ + getFile: function() { + return this.data.files[0]; + }, + + /** + * Return the final filename. + * Either this is the original file name or the file name + * after an autorename. + * + * @return {String} file name + */ + getFileName: function() { + // in case of autorename + if (this._newName) { + return this._newName; + } + + if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_AUTORENAME) { + + var locationUrl = this.getResponseHeader('Content-Location'); + if (locationUrl) { + this._newName = decodeURIComponent(OC.basename(locationUrl)); + return this._newName; + } + } + + return this.getFile().name; + }, + + setTargetFolder: function(targetFolder) { + this._targetFolder = targetFolder; + }, + + getTargetFolder: function() { + return this._targetFolder; + }, + + /** + * Get full path for the target file, including relative path, + * without the file name. + * + * @return {String} full path + */ + getFullPath: function() { + return OC.joinPaths(this._targetFolder, this.getFile().relativePath || ''); + }, + + /** + * Set conflict resolution mode. + * See CONFLICT_MODE_* constants. + */ + setConflictMode: function(mode) { + this._conflictMode = mode; + }, + + /** + * Returns whether the upload is in progress + * + * @return {bool} + */ + isPending: function() { + return this.data.state() === 'pending'; + }, + + deleteUpload: function() { + delete this.data.jqXHR; + }, + + /** + * Submit the upload + */ + submit: function() { + var data = this.data; + var file = this.getFile(); + + // it was a folder upload, so make sure the parent directory exists alrady + var folderPromise; + if (file.relativePath) { + folderPromise = this.uploader.ensureFolderExists(this.getFullPath()); + } else { + folderPromise = $.Deferred().resolve().promise(); + } + + if (this.uploader.fileList) { + this.data.url = this.uploader.fileList.getUploadUrl(file.name, this.getFullPath()); + } + + if (!this.data.headers) { + this.data.headers = {}; + } + + // webdav without multipart + this.data.multipart = false; + this.data.type = 'PUT'; + + delete this.data.headers['If-None-Match']; + if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_DETECT) { + this.data.headers['If-None-Match'] = '*'; + } else if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_AUTORENAME) { + // POST to parent folder, with slug + this.data.type = 'POST'; + this.data.url = this.uploader.fileList.getUploadUrl('&' + file.name, this.getFullPath()); + } + + if (file.lastModified) { + // preserve timestamp + this.data.headers['X-OC-Mtime'] = file.lastModified / 1000; + } + + if (!this.uploader.isXHRUpload()) { + data.formData = []; + + // pass headers as parameters + data.formData.push({name: 'headers', value: JSON.stringify(this.data.headers)}); + data.formData.push({name: 'requesttoken', value: OC.requestToken}); + if (data.type === 'POST') { + // still add the method to the URL + data.url += '?_method=POST'; + } + } + + // wait for creation of the required directory before uploading + folderPromise.then(function() { + data.submit(); + }, function() { + data.abort(); + }); + + }, + + /** + * Abort the upload + */ + abort: function() { + this.data.abort(); + }, + + /** + * Returns the server response + * + * @return {Object} response + */ + getResponse: function() { + var response = this.data.response(); + if (typeof response.result !== 'string') { + //fetch response from iframe + response = $.parseJSON(response.result[0].body.innerText); + if (!response) { + // likely due to internal server error + response = {status: 500}; + } + } else { + response = response.result; + } + return response; + }, + + /** + * Returns the status code from the response + * + * @return {int} status code + */ + getResponseStatus: function() { + if (this.uploader.isXHRUpload()) { + var xhr = this.data.response().jqXHR; + if (xhr) { + return xhr.status; + } + return null; + } + return this.getResponse().status; + }, + + /** + * Returns the response header by name + * + * @param {String} headerName header name + * @return {Array|String} response header value(s) + */ + getResponseHeader: function(headerName) { + headerName = headerName.toLowerCase(); + if (this.uploader.isXHRUpload()) { + return this.data.response().jqXHR.getResponseHeader(headerName); + } + + var headers = this.getResponse().headers; + if (!headers) { + return null; + } + + var value = _.find(headers, function(value, key) { + return key.toLowerCase() === headerName; }); - } else { - formData = _.extend(formData, newData); + if (_.isArray(value) && value.length === 1) { + return value[0]; + } + return value; } - return formData; -} +}; /** * keeps track of uploads in progress and implements callbacks for the conflicts dialog * @namespace */ -OC.Upload = { + +OC.Uploader = function() { + this.init.apply(this, arguments); +}; + +OC.Uploader.prototype = { + /** + * @type Array<OC.FileUpload> + */ _uploads: [], + /** - * deletes the jqHXR object from a data selection - * @param {object} data + * List of directories known to exist. + * + * Key is the fullpath and value is boolean, true meaning that the directory + * was already created so no need to create it again. + */ + _knownDirs: {}, + + /** + * @type OCA.Files.FileList + */ + fileList: null, + + /** + * @type OC.Files.Client + */ + filesClient: null, + + /** + * Function that will allow us to know if Ajax uploads are supported + * @link https://github.com/New-Bamboo/example-ajax-upload/blob/master/public/index.html + * also see article @link http://blog.new-bamboo.co.uk/2012/01/10/ridiculously-simple-ajax-uploads-with-formdata + */ + _supportAjaxUploadWithProgress: function() { + return supportFileAPI() && supportAjaxUploadProgressEvents() && supportFormData(); + + // Is the File API supported? + function supportFileAPI() { + var fi = document.createElement('INPUT'); + fi.type = 'file'; + return 'files' in fi; + } + + // Are progress events supported? + function supportAjaxUploadProgressEvents() { + var xhr = new XMLHttpRequest(); + return !! (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload)); + } + + // Is FormData supported? + function supportFormData() { + return !! window.FormData; + } + }, + + /** + * Returns whether an XHR upload will be used + * + * @return {bool} true if XHR upload will be used, + * false for iframe upload */ - deleteUpload:function(data) { - delete data.jqXHR; + isXHRUpload: function () { + return !this.fileUploadParam.forceIframeTransport && + ((!this.fileUploadParam.multipart && $.support.xhrFileUpload) || + $.support.xhrFormDataFileUpload); + }, + + /** + * Makes sure that the upload folder and its parents exists + * + * @param {String} fullPath full path + * @return {Promise} promise that resolves when all parent folders + * were created + */ + ensureFolderExists: function(fullPath) { + if (!fullPath || fullPath === '/') { + return $.Deferred().resolve().promise(); + } + + // remove trailing slash + if (fullPath.charAt(fullPath.length - 1) === '/') { + fullPath = fullPath.substr(0, fullPath.length - 1); + } + + var self = this; + var promise = this._knownDirs[fullPath]; + + if (this.fileList) { + // assume the current folder exists + this._knownDirs[this.fileList.getCurrentDirectory()] = $.Deferred().resolve().promise(); + } + + if (!promise) { + var deferred = new $.Deferred(); + promise = deferred.promise(); + this._knownDirs[fullPath] = promise; + + // make sure all parents already exist + var parentPath = OC.dirname(fullPath); + var parentPromise = this._knownDirs[parentPath]; + if (!parentPromise) { + parentPromise = this.ensureFolderExists(parentPath); + } + + parentPromise.then(function() { + self.filesClient.createDirectory(fullPath).always(function(status) { + // 405 is expected if the folder already exists + if ((status >= 200 && status < 300) || status === 405) { + self.$uploadEl.trigger($.Event('fileuploadcreatedfolder'), fullPath); + deferred.resolve(); + return; + } + OC.Notification.showTemporary(t('files', 'Could not create folder "{dir}"', {dir: fullPath})); + deferred.reject(); + }); + }, function() { + deferred.reject(); + }); + } + + return promise; + }, + + /** + * Submit the given uploads + * + * @param {Array} array of uploads to start + */ + submitUploads: function(uploads) { + var self = this; + _.each(uploads, function(upload) { + upload.submit(); + self._uploads[upload.data.uploadId] = upload; + }); + }, + + /** + * Show conflict for the given file object + * + * @param {OC.FileUpload} file upload object + */ + showConflict: function(fileUpload) { + //show "file already exists" dialog + var self = this; + var file = fileUpload.getFile(); + // retrieve more info about this file + this.filesClient.getFileInfo(fileUpload.getFullPath()).then(function(status, fileInfo) { + var original = fileInfo; + var replacement = file; + OC.dialogs.fileexists(fileUpload, original, replacement, self); + }); }, /** * cancels all uploads */ cancelUploads:function() { this.log('canceling uploads'); - jQuery.each(this._uploads, function(i, jqXHR) { - jqXHR.abort(); + jQuery.each(this._uploads, function(i, upload) { + upload.abort(); }); - this._uploads = []; + this.clear(); + }, + /** + * Clear uploads + */ + clear: function() { + this._uploads = {}; + this._knownDirs = {}; }, - rememberUpload:function(jqXHR) { - if (jqXHR) { - this._uploads.push(jqXHR); + /** + * Returns an upload by id + * + * @param {int} data uploadId + * @return {OC.FileUpload} file upload + */ + getUpload: function(data) { + if (_.isString(data)) { + return this._uploads[data]; + } else if (data.uploadId) { + return this._uploads[data.uploadId]; } + return null; }, + showUploadCancelMessage: _.debounce(function() { OC.Notification.showTemporary(t('files', 'Upload cancelled.'), {timeout: 10}); }, 500), @@ -106,8 +471,8 @@ OC.Upload = { isProcessing:function() { var count = 0; - jQuery.each(this._uploads, function(i, data) { - if (data.state() === 'pending') { + jQuery.each(this._uploads, function(i, upload) { + if (upload.isPending()) { count++; } }); @@ -115,9 +480,8 @@ OC.Upload = { }, /** * callback for the conflicts dialog - * @param {object} data */ - onCancel:function(data) { + onCancel:function() { this.cancelUploads(); }, /** @@ -147,43 +511,29 @@ OC.Upload = { }, /** * handle skipping an upload - * @param {object} data + * @param {OC.FileUpload} upload */ - onSkip:function(data) { - this.log('skip', null, data); - this.deleteUpload(data); + onSkip:function(upload) { + this.log('skip', null, upload); + upload.deleteUpload(); }, /** * handle replacing a file on the server with an uploaded file - * @param {object} data + * @param {FileUpload} data */ - onReplace:function(data) { - this.log('replace', null, data); - if (data.data) { - data.data.append('resolution', 'replace'); - } else { - if (!data.formData) { - data.formData = {}; - } - addFormData(data.formData, {resolution: 'replace'}); - } - data.submit(); + onReplace:function(upload) { + this.log('replace', null, upload); + upload.setConflictMode(OC.FileUpload.CONFLICT_MODE_OVERWRITE); + upload.submit(); }, /** * handle uploading a file and letting the server decide a new name - * @param {object} data + * @param {object} upload */ - onAutorename:function(data) { - this.log('autorename', null, data); - if (data.data) { - data.data.append('resolution', 'autorename'); - } else { - if (!data.formData) { - data.formData = {}; - } - addFormData(data.formData, {resolution: 'autorename'}); - } - data.submit(); + onAutorename:function(upload) { + this.log('autorename', null, upload); + upload.setConflictMode(OC.FileUpload.CONFLICT_MODE_AUTORENAME); + upload.submit(); }, _trace:false, //TODO implement log handler for JS per class? log:function(caption, e, data) { @@ -205,11 +555,20 @@ OC.Upload = { * @param {function} callbacks.onCancel */ checkExistingFiles: function (selection, callbacks) { - var fileList = FileList; + var fileList = this.fileList; var conflicts = []; // only keep non-conflicting uploads selection.uploads = _.filter(selection.uploads, function(upload) { - var fileInfo = fileList.findFile(upload.files[0].name); + var file = upload.getFile(); + if (file.relativePath) { + // can't check in subfolder contents + return true; + } + if (!fileList) { + // no list to check against + return true; + } + var fileInfo = fileList.findFile(file.name); if (fileInfo) { conflicts.push([ // original @@ -225,9 +584,9 @@ OC.Upload = { }); if (conflicts.length) { // wait for template loading - OC.dialogs.fileexists(null, null, null, OC.Upload).done(function() { + OC.dialogs.fileexists(null, null, null, this).done(function() { _.each(conflicts, function(conflictData) { - OC.dialogs.fileexists(conflictData[1], conflictData[0], conflictData[1].files[0], OC.Upload); + OC.dialogs.fileexists(conflictData[1], conflictData[0], conflictData[1].getFile(), this); }); }); } @@ -240,15 +599,26 @@ OC.Upload = { }, _hideProgressBar: function() { + var self = this; $('#uploadprogresswrapper .stop').fadeOut(); $('#uploadprogressbar').fadeOut(function() { - $('#file_upload_start').trigger(new $.Event('resized')); + self.$uploadEl.trigger(new $.Event('resized')); }); }, _showProgressBar: function() { $('#uploadprogressbar').fadeIn(); - $('#file_upload_start').trigger(new $.Event('resized')); + this.$uploadEl.trigger(new $.Event('resized')); + }, + + on: function() { + // forward events to upload element + this.$uploadEl.on.apply(this.$uploadEl, arguments); + }, + + off: function() { + // forward events to upload element + this.$uploadEl.off.apply(this.$uploadEl, arguments); }, /** @@ -269,12 +639,34 @@ OC.Upload = { return ($tr.attr('data-mounttype') === 'shared-root' && $tr.attr('data-mime') !== 'httpd/unix-directory'); }, - init: function() { + /** + * Initialize the upload object + * + * @param {Object} $uploadEl upload element + * @param {Object} options + * @param {OCA.Files.FileList} [options.fileList] file list object + * @param {OC.Files.Client} [options.filesClient] files client object + * @param {Object} [options.dropZone] drop zone for drag and drop upload + */ + init: function($uploadEl, options) { var self = this; - if ( $('#file_upload_start').exists() ) { - var file_upload_param = { - dropZone: $('#app-content'), // restrict dropZone to app-content div - pasteZone: null, + + options = options || {}; + + this.fileList = options.fileList; + this.filesClient = options.filesClient || OC.Files.getClient(); + + $uploadEl = $($uploadEl); + this.$uploadEl = $uploadEl; + + if ($uploadEl.exists()) { + $('#uploadprogresswrapper .stop').on('click', function() { + this.cancelUploads(); + }); + + this.fileUploadParam = { + type: 'PUT', + dropZone: options.dropZone, // restrict dropZone to content div autoUpload: false, sequentialUploads: true, //singleFileUploads is on by default, so the data.files array will always have length 1 @@ -295,9 +687,13 @@ OC.Upload = { * @returns {boolean} */ add: function(e, data) { - OC.Upload.log('add', e, data); + self.log('add', e, data); var that = $(this), freeSpace; + var upload = new OC.FileUpload(self, data); + // can't link directly due to jQuery not liking cyclic deps on its ajax object + data.uploadId = _.uniqueId('file-upload'); + // we need to collect all data upload objects before // starting the upload so we can check their existence // and set individual conflict actions. Unfortunately, @@ -317,16 +713,17 @@ OC.Upload = { biggestFileBytes: 0 }; } + // TODO: move originalFiles to a separate container, maybe inside OC.Upload var selection = data.originalFiles.selection; // add uploads if ( selection.uploads.length < selection.filesToUpload ) { // remember upload - selection.uploads.push(data); + selection.uploads.push(upload); } //examine file - var file = data.files[0]; + var file = upload.getFile(); try { // FIXME: not so elegant... need to refactor that method to return a value Files.isFileNameValid(file.name); @@ -336,9 +733,14 @@ OC.Upload = { data.errorThrown = errorMessage; } + if (data.targetDir) { + upload.setTargetFolder(data.targetDir); + delete data.targetDir; + } + // in case folder drag and drop is not supported file will point to a directory // http://stackoverflow.com/a/20448357 - if ( ! file.type && file.size%4096 === 0 && file.size <= 102400) { + if ( ! file.type && file.size % 4096 === 0 && file.size <= 102400) { var dirUploadFailure = false; try { var reader = new FileReader(); @@ -390,7 +792,7 @@ OC.Upload = { // end upload for whole selection on error if (data.errorThrown) { - // trigger fileupload fail + // trigger fileupload fail handler var fu = that.data('blueimp-fileupload') || that.data('fileupload'); fu._trigger('fail', e, data); return false; //don't upload anything @@ -405,9 +807,7 @@ OC.Upload = { var callbacks = { onNoConflicts: function (selection) { - $.each(selection.uploads, function(i, upload) { - upload.submit(); - }); + self.submitUploads(selection.uploads); }, onSkipConflicts: function (selection) { //TODO mark conflicting files as toskip @@ -425,7 +825,7 @@ OC.Upload = { } }; - OC.Upload.checkExistingFiles(selection, callbacks); + self.checkExistingFiles(selection, callbacks); } @@ -436,106 +836,54 @@ OC.Upload = { * @param {object} e */ start: function(e) { - OC.Upload.log('start', e, null); + self.log('start', e, null); //hide the tooltip otherwise it covers the progress bar $('#upload').tipsy('hide'); }, - submit: function(e, data) { - OC.Upload.rememberUpload(data); - if (!data.formData) { - data.formData = {}; - } - - var fileDirectory = ''; - if(typeof data.files[0].relativePath !== 'undefined') { - fileDirectory = data.files[0].relativePath; - } - - var params = { - requesttoken: oc_requesttoken, - dir: data.targetDir || FileList.getCurrentDirectory(), - file_directory: fileDirectory, - }; - if (data.files[0].isReceivedShare) { - params.isReceivedShare = true; - } - - addFormData(data.formData, params); - }, fail: function(e, data) { - OC.Upload.log('fail', e, data); - if (typeof data.textStatus !== 'undefined' && data.textStatus !== 'success' ) { - if (data.textStatus === 'abort') { - OC.Upload.showUploadCancelMessage(); - } else { - // HTTP connection problem - var message = t('files', 'Error uploading file "{fileName}": {message}', { - fileName: escapeHTML(data.files[0].name), - message: data.errorThrown - }, undefined, {escape: false}); - OC.Notification.show(message, {timeout: 0, type: 'error'}); - if (data.result) { - var result = JSON.parse(data.result); - if (result && result[0] && result[0].data && result[0].data.code === 'targetnotfound') { - // abort upload of next files if any - OC.Upload.cancelUploads(); - } - } - } + var upload = self.getUpload(data); + var status = upload.getResponseStatus(); + self.log('fail', e, upload); + + if (data.textStatus === 'abort') { + self.showUploadCancelMessage(); + } else if (status === 412) { + // file already exists + self.showConflict(upload); + } else if (status === 404) { + // target folder does not exist any more + OC.Notification.showTemporary( + t('files', 'Target folder "{dir}" does not exist any more', {dir: upload.getFullPath()}) + ); + self.cancelUploads(); + } else if (status === 507) { + // not enough space + OC.Notification.showTemporary( + t('files', 'Not enough free space') + ); + self.cancelUploads(); + } else { + // HTTP connection problem or other error + OC.Notification.showTemporary(data.errorThrown, {timeout: 10}); } - OC.Upload.deleteUpload(data); + upload.deleteUpload(); }, /** * called for every successful upload * @param {object} e * @param {object} data */ - done: function(e, data) { - OC.Upload.log('done', e, data); - // handle different responses (json or body from iframe for ie) - var response; - if (typeof data.result === 'string') { - response = data.result; - } else { - //fetch response from iframe - response = data.result[0].body.innerText; - } - var result = JSON.parse(response); + done:function(e, data) { + var upload = self.getUpload(data); + var that = $(this); + self.log('done', e, upload); - delete data.jqXHR; - - var fu = $(this).data('blueimp-fileupload') || $(this).data('fileupload'); - - if (result.status === 'error' && result.data && result.data.message){ - data.textStatus = 'servererror'; - data.errorThrown = result.data.message; - fu._trigger('fail', e, data); - } else if (typeof result[0] === 'undefined') { - data.textStatus = 'servererror'; - data.errorThrown = t('files', 'Could not get result from server.'); - fu._trigger('fail', e, data); - } else if (result[0].status === 'readonly') { - var original = result[0]; - var replacement = data.files[0]; - OC.dialogs.fileexists(data, original, replacement, OC.Upload); - } else if (result[0].status === 'existserror') { - //show "file already exists" dialog - var original = result[0]; - var replacement = data.files[0]; - OC.dialogs.fileexists(data, original, replacement, OC.Upload); - } else if (result[0].status !== 'success') { - //delete data.jqXHR; - data.textStatus = 'servererror'; - data.errorThrown = result[0].data.message; // error message has been translated on server + var status = upload.getResponseStatus(); + if (status < 200 || status >= 300) { + // trigger fail handler + var fu = that.data('blueimp-fileupload') || that.data('fileupload'); fu._trigger('fail', e, data); - } else { // Successful upload - // Checking that the uploaded file is the last one and contained in the current directory - if (data.files[0] === data.originalFiles[data.originalFiles.length - 1] && - result[0].directory === FileList.getCurrentDirectory()) { - // Scroll to the last uploaded file and highlight all of them - var fileList = _.pluck(data.originalFiles, 'name'); - FileList.highlightFiles(fileList); - } + return; } }, /** @@ -544,15 +892,14 @@ OC.Upload = { * @param {object} data */ stop: function(e, data) { - OC.Upload.log('stop', e, data); + self.log('stop', e, data); } }; // initialize jquery fileupload (blueimp) - var fileupload = $('#file_upload_start').fileupload(file_upload_param); - window.file_upload_param = fileupload; + var fileupload = this.$uploadEl.fileupload(this.fileUploadParam); - if (supportAjaxUploadWithProgress()) { + if (this._supportAjaxUploadWithProgress()) { //remaining time var lastUpdate = new Date().getMilliseconds(); var lastSize = 0; @@ -561,11 +908,12 @@ OC.Upload = { var bufferIndex = 0; var bufferTotal = 0; for(var i = 0; i < bufferSize;i++){ - buffer[i] = 0; + buffer[i] = 0; } + // add progress handlers fileupload.on('fileuploadadd', function(e, data) { - OC.Upload.log('progress handle fileuploadadd', e, data); + self.log('progress handle fileuploadadd', e, data); //show cancel button //if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie? // $('#uploadprogresswrapper .stop').show(); @@ -573,7 +921,7 @@ OC.Upload = { }); // add progress handlers fileupload.on('fileuploadstart', function(e, data) { - OC.Upload.log('progress handle fileuploadstart', e, data); + self.log('progress handle fileuploadstart', e, data); $('#uploadprogresswrapper .stop').show(); $('#uploadprogresswrapper .label').show(); $('#uploadprogressbar').progressbar({value: 0}); @@ -584,14 +932,14 @@ OC.Upload = { + t('files', '...') + '</span></em>'); $('#uploadprogressbar').tipsy({gravity:'n', fade:true, live:true}); - OC.Upload._showProgressBar(); + self._showProgressBar(); }); fileupload.on('fileuploadprogress', function(e, data) { - OC.Upload.log('progress handle fileuploadprogress', e, data); + self.log('progress handle fileuploadprogress', e, data); //TODO progressbar in row }); fileupload.on('fileuploadprogressall', function(e, data) { - OC.Upload.log('progress handle fileuploadprogressall', e, data); + self.log('progress handle fileuploadprogressall', e, data); var progress = (data.loaded / data.total) * 100; var thisUpdate = new Date().getMilliseconds(); var diffUpdate = (thisUpdate - lastUpdate)/1000; // eg. 2s @@ -608,14 +956,14 @@ OC.Upload = { var smoothRemainingSeconds = (bufferTotal / bufferSize); //seconds var date = new Date(smoothRemainingSeconds * 1000); var timeStringDesktop = ""; - var timeStringMobile = ""; + var timeStringMobile = ""; if(date.getUTCHours() > 0){ - timeStringDesktop = t('files', '{hours}:{minutes}:{seconds} hour{plural_s} left' , { + timeStringDesktop = t('files', '{hours}:{minutes}:{seconds} hour{plural_s} left' , { hours:date.getUTCHours(), minutes: ('0' + date.getUTCMinutes()).slice(-2), seconds: ('0' + date.getUTCSeconds()).slice(-2), plural_s: ( smoothRemainingSeconds === 3600 ? "": "s") // 1 hour = 1*60m*60s = 3600s - }); + }); timeStringMobile = t('files', '{hours}:{minutes}h' , { hours:date.getUTCHours(), minutes: ('0' + date.getUTCMinutes()).slice(-2), @@ -626,12 +974,12 @@ OC.Upload = { minutes: date.getUTCMinutes(), seconds: ('0' + date.getUTCSeconds()).slice(-2), plural_s: (smoothRemainingSeconds === 60 ? "": "s") // 1 minute = 1*60s = 60s - }); + }); timeStringMobile = t('files', '{minutes}:{seconds}m' , { minutes: date.getUTCMinutes(), seconds: ('0' + date.getUTCSeconds()).slice(-2) }); - } else if(date.getUTCSeconds() > 0){ + } else if(date.getUTCSeconds() > 0){ timeStringDesktop = t('files', '{seconds} second{plural_s} left' , { seconds: date.getUTCSeconds(), plural_s: (smoothRemainingSeconds === 1 ? "": "s") // 1 second = 1s = 1s @@ -653,14 +1001,16 @@ OC.Upload = { $('#uploadprogressbar').progressbar('value', progress); }); fileupload.on('fileuploadstop', function(e, data) { - OC.Upload.log('progress handle fileuploadstop', e, data); - OC.Upload._hideProgressBar(); + self.log('progress handle fileuploadstop', e, data); + + self.clear(); + self._hideProgressBar(); }); fileupload.on('fileuploadfail', function(e, data) { - OC.Upload.log('progress handle fileuploadfail', e, data); + self.log('progress handle fileuploadfail', e, data); //if user pressed cancel hide upload progress bar and cancel button if (data.errorThrown === 'abort') { - OC.Upload._hideProgressBar(); + self._hideProgressBar(); } }); var disableDropState = function() { @@ -715,36 +1065,20 @@ OC.Upload = { } } - $.assocArraySize = function(obj) { - // http://stackoverflow.com/a/6700/11236 - var size = 0, key; - for (key in obj) { - if (obj.hasOwnProperty(key)) { - size++; - } - } - return size; - }; - // warn user not to leave the page while upload is in progress $(window).on('beforeunload', function(e) { - if (OC.Upload.isProcessing()) { + if (self.isProcessing()) { return t('files', 'File upload is in progress. Leaving the page now will cancel the upload.'); } }); //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) if (navigator.userAgent.search(/konqueror/i) === -1) { - $('#file_upload_start').attr('multiple', 'multiple'); + this.$uploadEl.attr('multiple', 'multiple'); } - window.file_upload_param = file_upload_param; - return file_upload_param; + return this.fileUploadParam; } }; -$(document).ready(function() { - OC.Upload.init(); -}); - |