add support for inline image drag and drop to markdown editor

This commit is contained in:
Hiroyasu Nishiyama 2023-01-05 10:28:48 +09:00
parent 270eb56718
commit 7e8b7602b4
5 changed files with 98 additions and 7 deletions

View File

@ -53,6 +53,7 @@
"confirmDelete": "Confirm delete", "confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?", "delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here", "dropFlowHere": "Drop the flow here",
"dropImageHere": "Drop the image here",
"addFlow": "Add flow", "addFlow": "Add flow",
"addFlowToRight": "Add flow to the right", "addFlowToRight": "Add flow to the right",
"hideFlow": "Hide flow", "hideFlow": "Hide flow",

View File

@ -53,6 +53,7 @@
"confirmDelete": "削除の確認", "confirmDelete": "削除の確認",
"delete": "本当に '__label__' を削除しますか?", "delete": "本当に '__label__' を削除しますか?",
"dropFlowHere": "ここにフローをドロップしてください", "dropFlowHere": "ここにフローをドロップしてください",
"dropImageHere": "ここに画像ファイルをドロップしてください",
"addFlow": "フローの追加", "addFlow": "フローの追加",
"addFlowToRight": "右側にフローを追加", "addFlowToRight": "右側にフローを追加",
"hideFlow": "フローを非表示", "hideFlow": "フローを非表示",

View File

@ -45,6 +45,9 @@
selectedCodeEditor = RED.editor.codeEditor[defaultEditor]; selectedCodeEditor = RED.editor.codeEditor[defaultEditor];
initialised = selectedCodeEditor.init(); initialised = selectedCodeEditor.init();
} }
$('<div id="red-ui-image-drop-target"><div data-i18n="[append]workspace.dropImageHere"><i class="fa fa-download"></i><br></div></div>').appendTo('#red-ui-editor');
$("#red-ui-image-drop-target").hide();
} }
function create(options) { function create(options) {
@ -64,6 +67,7 @@
options = {}; options = {};
} }
var editor = null;
if (this.editor.type === MONACO) { if (this.editor.type === MONACO) {
// compatibility (see above note) // compatibility (see above note)
if (!options.element && !options.id) { if (!options.element && !options.id) {
@ -74,10 +78,14 @@
console.warn("createEditor() options.element or options.id is not valid", options); console.warn("createEditor() options.element or options.id is not valid", options);
$("#dialog-form").append('<div id="' + options.id + '" style="display: none;" />'); $("#dialog-form").append('<div id="' + options.id + '" style="display: none;" />');
} }
return this.editor.create(options); editor = this.editor.create(options);
} else { } else {
return this.editor.create(options);//fallback to ACE editor = this.editor.create(options);//fallback to ACE
} }
if (options.mode === "ace/mode/markdown") {
RED.editor.customEditTypes['_markdown'].postInit(editor, options);
}
return editor;
} }
return { return {

View File

@ -14,6 +14,55 @@
* limitations under the License. * limitations under the License.
**/ **/
(function() { (function() {
/**
* Converts dropped image file to date URL
*/
function file2base64Image(file, cb) {
var reader = new FileReader();
reader.onload = (function (fd) {
return function (e) {
cb(e.target.result);
};
})(file);
reader.readAsDataURL(file);
}
var initialized = false;
var currentEditor = null;
/**
* Initialize handler for image file drag events
*/
function initImageDrag(elem, editor) {
$(elem).on("dragenter", function (ev) {
ev.preventDefault();
$("#red-ui-image-drop-target").css({display:'table'}).focus();
currentEditor = editor;
});
if (!initialized) {
initialized = true;
$("#red-ui-image-drop-target").on("dragover", function (ev) {
ev.preventDefault();
}).on("dragleave", function (ev) {
$("#red-ui-image-drop-target").hide();
}).on("drop", function (ev) {
ev.preventDefault();
if ($.inArray("Files",ev.originalEvent.dataTransfer.types) != -1) {
var files = ev.originalEvent.dataTransfer.files;
if (files.length === 1) {
var file = files[0];
var image = file2base64Image(file, function (image) {
var session = currentEditor.getSession();
var img = `<img src="${image}"/>\n`;
var pos = session.getCursorPosition();
session.insert(pos, img);
$("#red-ui-image-drop-target").hide();
});
}
}
});
}
}
var toolbarTemplate = '<div style="margin-bottom: 5px">'+ var toolbarTemplate = '<div style="margin-bottom: 5px">'+
'<span class="button-group">'+ '<span class="button-group">'+
@ -148,10 +197,14 @@
}); });
RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview")); RED.popover.tooltip($("#node-btn-markdown-preview"), RED._("markdownEditor.toggle-preview"));
if (options.cursor && !expressionEditor._initState) { if(!expressionEditor._initState) {
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false); if (options.cursor) {
} expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
}
else {
expressionEditor.gotoLine(0, 0, false);
}
}
dialogForm.i18n(); dialogForm.i18n();
}, },
close: function() { close: function() {
@ -215,7 +268,11 @@
} }
}) })
return toolbar; return toolbar;
} },
postInit: function (editor, options) {
var elem = $("#"+options.id);
initImageDrag(elem, editor);
}
} }
RED.editor.registerTypeEditor("_markdown", definition); RED.editor.registerTypeEditor("_markdown", definition);
})(); })();

View File

@ -37,3 +37,27 @@
} }
} }
} }
#red-ui-image-drop-target {
position: absolute;
top: 0; bottom: 0;
left: 0; right: 0;
background: var(--red-ui-dnd-background);
display:table;
width: 100%;
height: 100%;
display: none;
z-index:100;
div {
pointer-events: none;
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 40px;
color: var(--red-ui-dnd-color);
i {
pointer-events: none;
font-size: 80px;
}
}
}