diff --git a/files/renderer.php b/files/renderer.php index 8d7c34e16d8..fe5415ab8e5 100644 --- a/files/renderer.php +++ b/files/renderer.php @@ -223,6 +223,7 @@ class core_files_renderer extends plugin_renderer_base { '.$strdndenabledinbox.'
'.$strdroptoupload.'
+
'.$icon_progress.'
'.$icon_progress.'
diff --git a/lib/form/dndupload.js b/lib/form/dndupload.js index 1e68cc8faf2..3a3a4b175e3 100644 --- a/lib/form/dndupload.js +++ b/lib/form/dndupload.js @@ -54,6 +54,8 @@ M.form_dndupload.init = function(Y, options) { // dragenter+dragleave(moving between child elements) and dragleave (leaving element) entercount: 0, pageentercount: 0, + // Holds the progress bar elements for each file. + progressbars: {}, /** * Initalise the drag and drop upload interface @@ -316,8 +318,12 @@ M.form_dndupload.init = function(Y, options) { repositoryid: this.repositoryid, currentfilecount: this.filemanager.filecount, // All files uploaded. currentfiles: this.filemanager.options.list, // Only the current folder. - callback: Y.bind('update_filemanager', this) + callback: Y.bind('update_filemanager', this), + callbackprogress: Y.bind('update_progress', this), + callbackcancel:Y.bind('hide_progress', this) }; + this.clear_progress(); + this.show_progress(); var uploader = new dnduploader(options); uploader.start_upload(); } else { @@ -328,8 +334,12 @@ M.form_dndupload.init = function(Y, options) { repositoryid: this.repositoryid, currentfilecount: 0, currentfiles: [], - callback: Y.bind('callback', this) + callback: Y.bind('update_filemanager', this), + callbackprogress: Y.bind('update_progress', this), + callbackcancel:Y.bind('hide_progress', this) }; + this.clear_progress(); + this.show_progress(); uploader = new dnduploader(options); uploader.start_upload(); } @@ -379,15 +389,68 @@ M.form_dndupload.init = function(Y, options) { this.container.removeClass('dndupload-over'); }, + /** + * Show the element showing the upload in progress + */ + show_progress: function() { + this.container.addClass('dndupload-inprogress'); + }, + + /** + * Hide the element showing upload in progress + */ + hide_progress: function() { + this.container.removeClass('dndupload-inprogress'); + }, + /** * Tell the attached filemanager element (if any) to refresh on file * upload */ - update_filemanager: function() { + update_filemanager: function(params) { + this.hide_progress(); if (this.filemanager) { // update the filemanager that we've uploaded the files this.filemanager.filepicker_callback(); + } else if (this.callback) { + this.callback(params); } + }, + + /** + * Clear the current progress bars + */ + clear_progress: function() { + var filename; + for (filename in this.progressbars) { + if (this.progressbars.hasOwnProperty(filename)) { + this.progressbars[filename].progressouter.remove(true); + delete this.progressbars[filename]; + } + } + }, + + /** + * Show the current progress of the uploaded file + */ + update_progress: function(filename, percent) { + if (this.progressbars[filename] === undefined) { + var dispfilename = filename; + if (dispfilename.length > 50) { + dispfilename = dispfilename.substr(0, 49)+'…'; + } + var progressouter = this.container.create(''+dispfilename+':  
'); + var progressinner = progressouter.one('.dndupload-progress-inner'); + var progresscontainer = this.container.one('.dndupload-progressbars'); + progresscontainer.appendChild(progressouter); + + this.progressbars[filename] = { + progressouter: progressouter, + progressinner: progressinner + }; + } + + this.progressbars[filename].progressinner.setStyle('width', percent + '%'); } }; @@ -402,6 +465,10 @@ M.form_dndupload.init = function(Y, options) { options: {}, // The function to call when all uploads complete. callback: null, + // The function to call as the upload progresses + callbackprogress: null, + // The function to call if the upload is cancelled + callbackcancel: null, // The list of files dropped onto the element. files: null, // The ID of the 'upload' repository. @@ -438,6 +505,8 @@ M.form_dndupload.init = function(Y, options) { this.options = params.options; this.repositoryid = params.repositoryid; this.callback = params.callback; + this.callbackprogress = params.callbackprogress; + this.callbackcancel = params.callbackcancel; this.currentfiles = params.currentfiles; this.currentfilecount = params.currentfilecount; this.currentareasize = 0; @@ -447,7 +516,11 @@ M.form_dndupload.init = function(Y, options) { this.currentareasize += this.currentfiles[i].size; }; - this.initialise_queue(params.files); + if (!this.initialise_queue(params.files)) { + if (this.callbackcancel) { + this.callbackcancel(); + } + } }, /** @@ -519,11 +592,12 @@ M.form_dndupload.init = function(Y, options) { this.renamequeue.push(files[i]); } else { if (!this.add_to_upload_queue(files[i], files[i].name, false)) { - return; + return false; } } this.queuesize += files[i].size; } + return true; }, /** @@ -633,6 +707,9 @@ M.form_dndupload.init = function(Y, options) { node.one('.fp-dlg-butcancel').on('click', function(e) { e.preventDefault(); process_dlg.hide(); + if (self.callbackcancel) { + self.callbackcancel(); + } }, this); // When we are at the file limit, only allow 'overwrite', not rename. @@ -775,6 +852,15 @@ M.form_dndupload.init = function(Y, options) { // http://yuilibrary.com/projects/yui3/ticket/2531274 var xhr = new XMLHttpRequest(); var self = this; + + // Update the progress bar + xhr.upload.addEventListener('progress', function(e) { + if (e.lengthComputable && self.callbackprogress) { + var percentage = Math.round((e.loaded * 100) / e.total); + self.callbackprogress(filename, percentage); + } + }, false); + xhr.onreadystatechange = function() { // Process the server response if (xhr.readyState == 4) { if (xhr.status == 200) { @@ -792,6 +878,9 @@ M.form_dndupload.init = function(Y, options) { result.url = result.newfile.url; } result.client_id = self.options.clientid; + if (self.callbackprogress) { + self.callbackprogress(filename, 100); + } } } self.do_upload(result); // continue uploading diff --git a/lib/form/filepicker.js b/lib/form/filepicker.js index b2811a25dbc..e3632e2f07e 100644 --- a/lib/form/filepicker.js +++ b/lib/form/filepicker.js @@ -5,6 +5,7 @@ M.form_filepicker.instances = []; M.form_filepicker.callback = function(params) { var html = ''+params['file']+''; + html += '
'; M.form_filepicker.Y.one('#file_info_'+params['client_id'] + ' .filepicker-filename').setContent(html); //When file is added then set status of global variable to true var elementname = M.core_filepicker.instances[params['client_id']].options.elementname; diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 45d9618c84b..791886cda27 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -2211,6 +2211,7 @@ EOD;
$currentfile$strdndenabled
+
{$strdroptoupload}
diff --git a/theme/base/pix/progress.gif b/theme/base/pix/progress.gif new file mode 100644 index 00000000000..0bc00dfa146 Binary files /dev/null and b/theme/base/pix/progress.gif differ diff --git a/theme/base/style/course.css b/theme/base/style/course.css index 1bd7200113b..aff2b696ceb 100644 --- a/theme/base/style/course.css +++ b/theme/base/style/course.css @@ -204,6 +204,6 @@ input.titleeditor { width: 330px; vertical-align: text-bottom; } #dndupload-status {width:40%;margin:0 30%;padding:6px;border:1px solid #ddd;text-align:center;background:#ffc;position:absolute;z-index:9999;box-shadow:2px 2px 5px 1px #ccc;border-radius:0px 0px 8px 8px;z-index: 0;} .dndupload-preview {color:#909090;border:1px dashed #909090;list-style:none; margin-top: .2em; padding: .3em; line-height: 16px;} .dndupload-preview img.icon { vertical-align: text-bottom; padding: 0;} -.dndupload-progress-outer {width:70px;border:1px solid black;height:10px;display:inline-block;margin:0;padding:0;overflow:hidden;position:relative;} -.dndupload-progress-inner {width:0%;height:100%;background-color:green;display:inline-block;margin:0;padding:0;float:left;} +.dndupload-progress-outer {width:70px;border:1px solid black;border-radius:4px;height:10px;display:inline-block;margin:0;padding:0;overflow:hidden;position:relative;} +.dndupload-progress-inner {width:0%;height:100%;background-color:green;display:inline-block;margin:0;padding:0;float:left;box-shadow: 0 0 4px #229b15;border-radius:2px;background-repeat:repeat-x;background-position:top;background-image:url([[pix:theme_base|progress]])} .dndupload-hidden {display:none;} diff --git a/theme/base/style/filemanager.css b/theme/base/style/filemanager.css index ed52934b7ea..b9706ac41dc 100644 --- a/theme/base/style/filemanager.css +++ b/theme/base/style/filemanager.css @@ -347,6 +347,12 @@ a.ygtvspacer:hover {color: transparent;text-decoration: none;} .dndupload-uploading .dndupload-uploadinprogress {display:block;} .dndupload-arrow {background:url([[pix:theme|fp/dnd_arrow]]) center no-repeat;width:60px;height:80px;position:absolute;margin-left: -28px;top: 5px;} .fitem.disabled .filepicker-container, .fitem.disabled .fm-empty-container {display:none;} +.dndupload-progressbars {padding:10px;display:none;} +.dndupload-inprogress .dndupload-progressbars {display:block;} +.dndupload-inprogress .fp-content {display:none;} +.filemanager.fm-noitems .dndupload-inprogress .fm-empty-container {display:none;} +.filepicker-filelist.dndupload-inprogress .filepicker-container {display:none;} +.filepicker-filelist.dndupload-inprogress a {display:none;} /* * Select Dialogue (File Manager only)