mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
380 lines
16 KiB
JavaScript
380 lines
16 KiB
JavaScript
/**
|
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
**/
|
|
|
|
|
|
RED.clipboard = (function() {
|
|
|
|
var dialog;
|
|
var dialogContainer;
|
|
var exportNodesDialog;
|
|
var importNodesDialog;
|
|
var disabled = false;
|
|
|
|
function setupDialogs() {
|
|
dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>')
|
|
.appendTo("body")
|
|
.dialog({
|
|
modal: true,
|
|
autoOpen: false,
|
|
width: 500,
|
|
resizable: false,
|
|
buttons: [
|
|
{
|
|
id: "clipboard-dialog-cancel",
|
|
text: RED._("common.label.cancel"),
|
|
click: function() {
|
|
$( this ).dialog( "close" );
|
|
}
|
|
},
|
|
{
|
|
id: "clipboard-dialog-close",
|
|
class: "primary",
|
|
text: RED._("common.label.close"),
|
|
click: function() {
|
|
$( this ).dialog( "close" );
|
|
}
|
|
},
|
|
{
|
|
id: "clipboard-dialog-copy",
|
|
class: "primary",
|
|
text: RED._("clipboard.export.copy"),
|
|
click: function() {
|
|
$("#clipboard-export").select();
|
|
document.execCommand("copy");
|
|
document.getSelection().removeAllRanges();
|
|
RED.notify(RED._("clipboard.nodesExported"));
|
|
$( this ).dialog( "close" );
|
|
}
|
|
},
|
|
{
|
|
id: "clipboard-dialog-ok",
|
|
class: "primary",
|
|
text: RED._("common.label.import"),
|
|
click: function() {
|
|
RED.view.importNodes($("#clipboard-import").val(),$("#import-tab > a.selected").attr('id') === 'import-tab-new');
|
|
$( this ).dialog( "close" );
|
|
}
|
|
}
|
|
],
|
|
open: function(e) {
|
|
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
|
},
|
|
close: function(e) {
|
|
}
|
|
});
|
|
|
|
dialogContainer = dialog.children(".dialog-form");
|
|
|
|
exportNodesDialog =
|
|
'<div class="form-row">'+
|
|
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.export.copy"></label>'+
|
|
'<span id="export-range-group" class="button-group">'+
|
|
'<a id="export-range-selected" class="editor-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
|
|
'<a id="export-range-flow" class="editor-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
|
|
'<a id="export-range-full" class="editor-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
|
|
'</span>'+
|
|
'</div>'+
|
|
'<div class="form-row">'+
|
|
'<textarea readonly style="resize: none; width: 100%; border-radius: 4px;font-family: monospace; font-size: 12px; background:#f3f3f3; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
|
|
'</div>'+
|
|
'<div class="form-row" style="text-align: right;">'+
|
|
'<span id="export-format-group" class="button-group">'+
|
|
'<a id="export-format-mini" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
|
'<a id="export-format-full" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
|
'</span>'+
|
|
'</div>';
|
|
|
|
importNodesDialog = '<div class="form-row">'+
|
|
'<textarea style="resize: none; width: 100%; border-radius: 0px;font-family: monospace; font-size: 12px; background:#eee; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-import" rows="5" placeholder="'+
|
|
RED._("clipboard.pasteNodes")+
|
|
'"></textarea>'+
|
|
'</div>'+
|
|
'<div class="form-row">'+
|
|
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.import.import"></label>'+
|
|
'<span id="import-tab" class="button-group">'+
|
|
'<a id="import-tab-current" class="editor-button toggle selected" href="#" data-i18n="clipboard.export.current"></a>'+
|
|
'<a id="import-tab-new" class="editor-button toggle" href="#" data-i18n="clipboard.import.newFlow"></a>'+
|
|
'</span>'+
|
|
'</div>';
|
|
}
|
|
|
|
function validateImport() {
|
|
var importInput = $("#clipboard-import");
|
|
var v = importInput.val();
|
|
v = v.substring(v.indexOf('['),v.lastIndexOf(']')+1);
|
|
try {
|
|
JSON.parse(v);
|
|
importInput.removeClass("input-error");
|
|
importInput.val(v);
|
|
$("#clipboard-dialog-ok").button("enable");
|
|
} catch(err) {
|
|
if (v !== "") {
|
|
importInput.addClass("input-error");
|
|
}
|
|
$("#clipboard-dialog-ok").button("disable");
|
|
}
|
|
}
|
|
|
|
function importNodes() {
|
|
if (disabled) {
|
|
return;
|
|
}
|
|
dialogContainer.empty();
|
|
dialogContainer.append($(importNodesDialog));
|
|
dialogContainer.i18n();
|
|
|
|
$("#clipboard-dialog-ok").show();
|
|
$("#clipboard-dialog-cancel").show();
|
|
$("#clipboard-dialog-close").hide();
|
|
$("#clipboard-dialog-copy").hide();
|
|
$("#clipboard-dialog-ok").button("disable");
|
|
$("#clipboard-import").keyup(validateImport);
|
|
$("#clipboard-import").on('paste',function() { setTimeout(validateImport,10)});
|
|
|
|
$("#import-tab > a").click(function(evt) {
|
|
evt.preventDefault();
|
|
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
|
return;
|
|
}
|
|
$(this).parent().children().removeClass('selected');
|
|
$(this).addClass('selected');
|
|
});
|
|
|
|
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
|
|
}
|
|
|
|
function exportNodes() {
|
|
if (disabled) {
|
|
return;
|
|
}
|
|
|
|
dialogContainer.empty();
|
|
dialogContainer.append($(exportNodesDialog));
|
|
dialogContainer.i18n();
|
|
var format = RED.settings.flowFilePretty ? "export-format-full" : "export-format-mini";
|
|
|
|
$("#export-format-group > a").click(function(evt) {
|
|
evt.preventDefault();
|
|
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
|
$("#clipboard-export").focus();
|
|
return;
|
|
}
|
|
$(this).parent().children().removeClass('selected');
|
|
$(this).addClass('selected');
|
|
|
|
var flow = $("#clipboard-export").val();
|
|
if (flow.length > 0) {
|
|
var nodes = JSON.parse(flow);
|
|
|
|
format = $(this).attr('id');
|
|
if (format === 'export-format-full') {
|
|
flow = JSON.stringify(nodes,null,4);
|
|
} else {
|
|
flow = JSON.stringify(nodes);
|
|
}
|
|
$("#clipboard-export").val(flow);
|
|
$("#clipboard-export").focus();
|
|
}
|
|
});
|
|
|
|
$("#export-range-group > a").click(function(evt) {
|
|
evt.preventDefault();
|
|
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
|
$("#clipboard-export").focus();
|
|
return;
|
|
}
|
|
$(this).parent().children().removeClass('selected');
|
|
$(this).addClass('selected');
|
|
var type = $(this).attr('id');
|
|
var flow = "";
|
|
var nodes = null;
|
|
if (type === 'export-range-selected') {
|
|
var selection = RED.view.selection();
|
|
// Don't include the subflow meta-port nodes in the exported selection
|
|
nodes = RED.nodes.createExportableNodeSet(selection.nodes.filter(function(n) { return n.type !== 'subflow'}));
|
|
} else if (type === 'export-range-flow') {
|
|
var activeWorkspace = RED.workspaces.active();
|
|
nodes = RED.nodes.filterNodes({z:activeWorkspace});
|
|
var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
|
|
nodes.unshift(parentNode);
|
|
nodes = RED.nodes.createExportableNodeSet(nodes);
|
|
} else if (type === 'export-range-full') {
|
|
nodes = RED.nodes.createCompleteNodeSet(false);
|
|
}
|
|
if (nodes !== null) {
|
|
if (format === "export-format-full") {
|
|
flow = JSON.stringify(nodes,null,4);
|
|
} else {
|
|
flow = JSON.stringify(nodes);
|
|
}
|
|
}
|
|
if (flow.length > 0) {
|
|
$("#export-copy").removeClass('disabled');
|
|
} else {
|
|
$("#export-copy").addClass('disabled');
|
|
}
|
|
$("#clipboard-export").val(flow);
|
|
$("#clipboard-export").focus();
|
|
})
|
|
|
|
$("#clipboard-dialog-ok").hide();
|
|
$("#clipboard-dialog-cancel").hide();
|
|
$("#clipboard-dialog-copy").hide();
|
|
$("#clipboard-dialog-close").hide();
|
|
var selection = RED.view.selection();
|
|
if (selection.nodes) {
|
|
$("#export-range-selected").click();
|
|
} else {
|
|
$("#export-range-selected").addClass('disabled').removeClass('selected');
|
|
$("#export-range-flow").click();
|
|
}
|
|
if (format === "export-format-full") {
|
|
$("#export-format-full").click();
|
|
} else {
|
|
$("#export-format-mini").click();
|
|
}
|
|
$("#clipboard-export")
|
|
.focus(function() {
|
|
var textarea = $(this);
|
|
textarea.select();
|
|
textarea.mouseup(function() {
|
|
textarea.unbind("mouseup");
|
|
return false;
|
|
})
|
|
});
|
|
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
|
|
|
|
$("#clipboard-export").focus();
|
|
if (!document.queryCommandSupported("copy")) {
|
|
$("#clipboard-dialog-cancel").hide();
|
|
$("#clipboard-dialog-close").show();
|
|
} else {
|
|
$("#clipboard-dialog-cancel").show();
|
|
$("#clipboard-dialog-copy").show();
|
|
}
|
|
}
|
|
|
|
function hideDropTarget() {
|
|
$("#dropTarget").hide();
|
|
RED.keyboard.remove("escape");
|
|
}
|
|
function copyText(value,element,msg) {
|
|
var truncated = false;
|
|
if (typeof value !== "string" ) {
|
|
value = JSON.stringify(value, function(key,value) {
|
|
if (value !== null && typeof value === 'object') {
|
|
if (value.__enc__) {
|
|
if (value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
|
|
truncated = value.data.length !== value.length;
|
|
return value.data;
|
|
}
|
|
if (value.type === 'function' || value.type === 'internal') {
|
|
return undefined
|
|
}
|
|
if (value.type === 'number') {
|
|
// Handle NaN and Infinity - they are not permitted
|
|
// in JSON. We can either substitute with a String
|
|
// representation or null
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
});
|
|
}
|
|
if (truncated) {
|
|
msg += "_truncated";
|
|
}
|
|
$("#clipboard-hidden").val(value).select();
|
|
var result = document.execCommand("copy");
|
|
if (result && element) {
|
|
var popover = RED.popover.create({
|
|
target: element,
|
|
direction: 'left',
|
|
size: 'small',
|
|
content: RED._(msg)
|
|
});
|
|
setTimeout(function() {
|
|
popover.close();
|
|
},1000);
|
|
popover.open();
|
|
}
|
|
return result;
|
|
}
|
|
return {
|
|
init: function() {
|
|
setupDialogs();
|
|
|
|
$('<input type="text" id="clipboard-hidden">').appendTo("body");
|
|
|
|
RED.actions.add("core:show-export-dialog",exportNodes);
|
|
RED.actions.add("core:show-import-dialog",importNodes);
|
|
|
|
|
|
RED.events.on("editor:open",function() { disabled = true; });
|
|
RED.events.on("editor:close",function() { disabled = false; });
|
|
RED.events.on("search:open",function() { disabled = true; });
|
|
RED.events.on("search:close",function() { disabled = false; });
|
|
RED.events.on("type-search:open",function() { disabled = true; });
|
|
RED.events.on("type-search:close",function() { disabled = false; });
|
|
|
|
|
|
$('#chart').on("dragenter",function(event) {
|
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
|
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
|
$("#dropTarget").css({display:'table'});
|
|
RED.keyboard.add("*", "escape" ,hideDropTarget);
|
|
}
|
|
});
|
|
|
|
$('#dropTarget').on("dragover",function(event) {
|
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
|
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
|
event.preventDefault();
|
|
}
|
|
})
|
|
.on("dragleave",function(event) {
|
|
hideDropTarget();
|
|
})
|
|
.on("drop",function(event) {
|
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
|
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
|
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
|
|
RED.view.importNodes(data);
|
|
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
|
var files = event.originalEvent.dataTransfer.files;
|
|
if (files.length === 1) {
|
|
var file = files[0];
|
|
var reader = new FileReader();
|
|
reader.onload = (function(theFile) {
|
|
return function(e) {
|
|
RED.view.importNodes(e.target.result);
|
|
};
|
|
})(file);
|
|
reader.readAsText(file);
|
|
}
|
|
}
|
|
hideDropTarget();
|
|
event.preventDefault();
|
|
});
|
|
|
|
},
|
|
import: importNodes,
|
|
export: exportNodes,
|
|
copyText: copyText
|
|
}
|
|
})();
|