From 14f7c2ccc04630f5db9788ef5c911ffe351cf792 Mon Sep 17 00:00:00 2001 From: Julien Rebetez Date: Sat, 23 Apr 2016 10:27:53 +0200 Subject: [PATCH] Better handling of dnd events to correctly remove the dropzone effect when escape is pressed. --- notebook/static/base/js/utils.js | 17 ++++++++++++++ notebook/static/notebook/js/textcell.js | 30 ++++++++++++------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/notebook/static/base/js/utils.js b/notebook/static/base/js/utils.js index 49178cfd4..cf9ed588a 100644 --- a/notebook/static/base/js/utils.js +++ b/notebook/static/base/js/utils.js @@ -946,6 +946,22 @@ define([ } }; + // Test if a drag'n'drop event contains a file (as opposed to an HTML + // element/text from the document) + var dnd_contain_file = function(event) { + // As per the HTML5 drag'n'drop spec, the dataTransfer.types should + // contain one "Files" type if a file is being dragged + // https://www.w3.org/TR/2011/WD-html5-20110113/dnd.html#dom-datatransfer-types + if (event.dataTransfer.types) { + for (var i = 0; i < event.dataTransfer.types.length; i++) { + if (event.dataTransfer.types[i] == "Files") { + return true; + } + } + } + return false; + }; + var utils = { is_loaded: is_loaded, load_extension: load_extension, @@ -990,6 +1006,7 @@ define([ time: time, format_datetime: format_datetime, datetime_sort_helper: datetime_sort_helper, + dnd_contain_file: dnd_contain_file, _ansispan:_ansispan }; diff --git a/notebook/static/notebook/js/textcell.js b/notebook/static/notebook/js/textcell.js index 259453e6c..64d613710 100644 --- a/notebook/static/notebook/js/textcell.js +++ b/notebook/static/notebook/js/textcell.js @@ -458,19 +458,15 @@ define([ } }); - // Allow drop event if the dragged file can be used as an attachment - this.code_mirror.on("dragstart", function(cm, evt) { - var files = evt.dataTransfer.files; - for (var i = 0; i < files.length; ++i) { - var file = files[i]; - if (attachment_regex.test(file.type)) { - return false; - } + // Allow drag event if the dragged file can be used as an attachment + // If we use this.code_mirror.on to register a "dragover" handler, we + // get an empty dataTransfer + this.code_mirror.on("dragover", function(cm, evt) { + if (utils.dnd_contain_file(evt)) { + evt.preventDefault(); } - return true; }); - // We want to display a visual indicator that the drop is possible. // The dragleave event is fired when we hover a child element (which // is often immediatly after we got the dragenter), so we keep track @@ -479,25 +475,27 @@ define([ // This doesn't seem to be 100% reliable, so we clear the dropzone // class when the cell is rendered as well this.code_mirror.on("dragenter", function(cm, evt) { - that.drag_counter++; - that.inner_cell.addClass('dropzone'); - // prevent default to allow drop - evt.stopPropagation(); + if (utils.dnd_contain_file(evt)) { + that.drag_counter++; + that.inner_cell.addClass('dropzone'); + } evt.preventDefault(); + evt.stopPropagation(); }); this.code_mirror.on("dragleave", function(cm, evt) { that.drag_counter--; - if (that.drag_counter === 0) { + if (that.drag_counter <= 0) { that.inner_cell.removeClass('dropzone'); } - evt.stopPropagation(); evt.preventDefault(); + evt.stopPropagation(); }); this.code_mirror.on("drop", function(cm, evt) { that.drag_counter = 0; that.inner_cell.removeClass('dropzone'); + var files = evt.dataTransfer.files; for (var i = 0; i < files.length; ++i) { var file = files[i];