MDL-31114 Filemanager drag and drop upload - displays 'drop here' message when draggi...
authorDavo Smith <git@davosmith.co.uk>
Tue, 14 Feb 2012 10:12:58 +0000 (10:12 +0000)
committerDavo Smith <git@davosmith.co.uk>
Tue, 14 Feb 2012 10:12:58 +0000 (10:12 +0000)
lib/form/dndupload.js
lib/form/filemanager.js
lib/form/filemanager.php
lib/form/filepicker.js
theme/base/style/core.css

index 40018a3..b09e1a5 100644 (file)
@@ -51,7 +51,7 @@ M.form_dndupload.init = function(Y, options) {
         // Nasty hack to distinguish between dragenter(first entry),
         // dragenter+dragleave(moving between child elements) and dragleave (leaving element)
         entercount: 0,
-
+        pageentercount: 0,
 
         /**
          * Initalise the drag and drop upload interface
@@ -108,6 +108,7 @@ M.form_dndupload.init = function(Y, options) {
             }
 
             this.init_events();
+            this.init_page_events();
             this.Y.one('#dndenabled-'+this.clientid).setStyle('display', 'inline');
         },
 
@@ -153,6 +154,51 @@ M.form_dndupload.init = function(Y, options) {
             this.Y.on('drop',      this.drop,      this.container, this);
         },
 
+        /**
+         * Initialise whole-page events (to show / hide the 'drop files here'
+         * message)
+         */
+        init_page_events: function() {
+            this.Y.on('dragenter', this.drag_enter_page, 'body', this);
+            this.Y.on('dragleave', this.drag_leave_page, 'body', this);
+        },
+
+        /**
+         * Show the 'drop files here' message when file(s) are dragged
+         * onto the page
+         */
+        drag_enter_page: function(e) {
+            if (!this.has_files(e) || this.reached_maxfiles()) {
+                return false;
+            }
+
+            this.pageentercount++;
+            if (this.pageentercount >= 2) {
+                this.pageentercount = 2;
+                return false;
+            }
+
+            this.show_drop_target();
+
+            return false;
+        },
+
+        /**
+         * Hide the 'drop files here' message when file(s) are dragged off
+         * the page again
+         */
+        drag_leave_page: function(e) {
+            this.pageentercount--;
+            if (this.pageentercount == 1) {
+                return false;
+            }
+            this.pageentercount = 0;
+
+            this.hide_drop_target();
+
+            return false;
+        },
+
         /**
          * Check if the drag contents are valid and then call
          * preventdefault / stoppropagation to let the browser know
@@ -194,6 +240,12 @@ M.form_dndupload.init = function(Y, options) {
                 return false;
             }
 
+            // These lines are needed if the user has dragged something directly
+            // from application onto the 'fileupload' box, without crossing another
+            // part of the page first
+            this.pageentercount = 2;
+            this.show_drop_target();
+
             this.show_upload_ready();
             return false;
         },
@@ -239,7 +291,9 @@ M.form_dndupload.init = function(Y, options) {
             }
 
             this.entercount = 0;
+            this.pageentercount = 0;
             this.hide_upload_ready();
+            this.hide_drop_target();
             this.show_progress_spinner();
 
             var files = e._event.dataTransfer.files;
@@ -294,7 +348,18 @@ M.form_dndupload.init = function(Y, options) {
         },
 
         /**
-         * Highlight the destination node
+         * Highlight the area where files could be dropped
+         */
+        show_drop_target: function() {
+            this.Y.one('#filemanager-uploadmessage'+this.clientid).setStyle('display', 'block');
+        },
+
+        hide_drop_target: function() {
+            this.Y.one('#filemanager-uploadmessage'+this.clientid).setStyle('display', 'none');
+        },
+
+        /**
+         * Highlight the destination node (ready to drop)
          */
         show_upload_ready: function() {
             this.container.addClass('dndupload-over');
@@ -321,7 +386,10 @@ M.form_dndupload.init = function(Y, options) {
          * Remove progress spinner in the destination node
          */
         hide_progress_spinner: function() {
-            this.Y.one('#dndprogresspinner-'+this.clientid).remove();
+            var spinner = this.Y.one('#dndprogresspinner-'+this.clientid);
+            if (spinner) {
+                spinner.remove();
+            }
         },
 
         /**
index d3d237b..de89ff3 100644 (file)
@@ -264,7 +264,13 @@ M.form_filemanager.init = function(Y, options) {
             }, this);
         },
         empty_filelist: function(container) {
-            container.set('innerHTML', '<div class="mdl-align">'+M.str.repository.nofilesattached+'</div>');
+            container.set('innerHTML', '<div class="mdl-align">'+M.str.repository.nofilesattached+'</div>'+this.upload_message());
+        },
+        upload_message: function() {
+            var div = '<div id="filemanager-uploadmessage'+this.client_id+'" style="display:none" class="dndupload-target">';
+            div += M.util.get_string('droptoupload', 'moodle');
+            div += '</div>';
+            return div;
         },
         render: function() {
             var options = this.options;
@@ -415,6 +421,7 @@ M.form_filemanager.init = function(Y, options) {
                 var filelist = Y.Node.create('<ul id="draftfiles-'+this.client_id+'"></ul>');
                 container.appendChild(filelist);
             }
+            listhtml += this.upload_message();
             Y.one('#draftfiles-'+this.client_id).set('innerHTML', listhtml);
 
             // click normal file menu
index 1d93585..7d42d81 100644 (file)
@@ -288,7 +288,7 @@ $icon_progress
         <span> $maxsize </span>
         <span id="dndenabled-{$client_id}" style="display: none"> - $strdndenabled </span>
     </div>
-    <div class="filemanager-container" id="filemanager-{$client_id}">
+    <div class="filemanager-container" id="filemanager-{$client_id}" style="position: relative" >
         <ul id="draftfiles-{$client_id}" class="fm-filelist">
             <li>Loading...</li>
         </ul>
index 51d8ef6..4c99ea8 100644 (file)
@@ -6,6 +6,7 @@ M.form_filepicker.instances = [];
 M.form_filepicker.callback = function(params) {
     var html = '<a href="'+params['url']+'">'+params['file']+'</a>';
     document.getElementById('file_info_'+params['client_id']).innerHTML = html;
+    M.form_filepicker.add_upload_message(params['client_id']);
     //When file is added then set status of global variable to true
     var elementname = M.core_filepicker.instances[params['client_id']].options.elementname;
     M.form_filepicker.instances[elementname].fileadded = true;
@@ -13,6 +14,15 @@ M.form_filepicker.callback = function(params) {
     M.form_filepicker.Y.one('#id_'+elementname).simulate('change');
 };
 
+M.form_filepicker.add_upload_message = function(client_id) {
+    var div = '<div id="filemanager-uploadmessage'+client_id+'" style="display:none" class="dndupload-target">';
+    div += M.util.get_string('droptoupload', 'moodle');
+    div += '</div>';
+    var iteminfo = document.getElementById('file_info_'+client_id);
+    iteminfo.innerHTML += div;
+    iteminfo.style.position = 'relative';
+}
+
 /**
  * This fucntion is called for each file picker on page.
  */
@@ -42,6 +52,7 @@ M.form_filepicker.init = function(Y, options) {
     item = document.getElementById('filepicker-wrapper-'+options.client_id);
     if (item) {
         item.style.display = '';
+        this.add_upload_message(options.client_id);
     }
 
     var dndoptions = {
index d7c95c8..c7fed78 100644 (file)
@@ -532,8 +532,12 @@ body.tag .managelink {padding: 5px;}
 .fm-file-entry{border: 1px solid red;}
 .fm-operation {font-weight: bold;}
 
-.filemanager-container.dndupload-over,
-.filepicker-filelist.dndupload-over {background: #8EF947;}
+.filemanager-container,
+.filepicker-filelist {overflow:hidden;}
+.filemanager-container .dndupload-target,
+.filepicker-filelist .dndupload-target {background:#f7f998;position:absolute;height:100%;width:100%;top:0;left:0;text-align:center;padding:5px;z-index:1000}
+.filemanager-container.dndupload-over .dndupload-target,
+.filepicker-filelist.dndupload-over .dndupload-target {background:#8EF947;font-weight:bold}
 
 /*
  * Backup and Restore CSS