/** * 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; var popover; var currentPopoverError; var activeTab; var libraryBrowser; function setupDialogs() { dialog = $('
') .appendTo("body") .dialog({ modal: true, autoOpen: false, width: 700, resizable: false, buttons: [ { id: "clipboard-dialog-cancel", text: RED._("common.label.cancel"), click: function() { $( this ).dialog( "close" ); } }, { id: "clipboard-dialog-download", class: "primary", text: RED._("clipboard.download"), click: function() { var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent($("#clipboard-export").val())); element.setAttribute('download', "flows.json"); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); $( this ).dialog( "close" ); } }, { id: "clipboard-dialog-export", class: "primary", text: RED._("clipboard.export.copy"), click: function() { if (activeTab === "clipboard-dialog-export-tab-clipboard") { $("#clipboard-export").select(); document.execCommand("copy"); document.getSelection().removeAllRanges(); RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"}); $( this ).dialog( "close" ); } else { var flowToExport = $("#clipboard-export").val(); var selectedPath = libraryBrowser.getSelected(); if (!selectedPath.children) { selectedPath = selectedPath.parent; } var filename = $("#clipboard-dialog-tab-library-name").val().trim(); var saveFlow = function() { $.ajax({ url:'library/'+selectedPath.library+'/'+selectedPath.type+'/'+selectedPath.path + filename, type: "POST", data: flowToExport, contentType: "application/json; charset=utf-8" }).done(function() { $(dialog).dialog( "close" ); RED.notify(RED._("library.exportedToLibrary"),"success"); }).fail(function(xhr,textStatus,err) { if (xhr.status === 401) { RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error"); } else { RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error"); } }); } if (selectedPath.children) { var exists = false; selectedPath.children.forEach(function(f) { if (f.label === filename) { exists = true; } }); if (exists) { dialog.dialog("close"); var notification = RED.notify(RED._("clipboard.export.exists",{file:RED.utils.sanitize(filename)}),{ type: "warning", fixed: true, buttons: [{ text: RED._("common.label.cancel"), click: function() { notification.hideNotification() dialog.dialog( "open" ); } },{ text: RED._("clipboard.export.overwrite"), click: function() { notification.hideNotification() saveFlow(); } }] }); } else { saveFlow(); } } else { saveFlow(); } } } }, { id: "clipboard-dialog-ok", class: "primary", text: RED._("common.label.import"), click: function() { var addNewFlow = ($("#import-tab > a.selected").attr('id') === 'import-tab-new'); if (activeTab === "clipboard-dialog-import-tab-clipboard") { RED.view.importNodes($("#clipboard-import").val(),addNewFlow); } else { var selectedPath = libraryBrowser.getSelected(); if (selectedPath.path) { $.get('library/'+selectedPath.library+'/'+selectedPath.type+'/'+selectedPath.path, function(data) { RED.view.importNodes(data,addNewFlow); }); } } $( this ).dialog( "close" ); } } ], open: function(e) { $(this).parent().find(".ui-dialog-titlebar-close").hide(); }, close: function(e) { if (popover) { popover.close(true); currentPopoverError = null; } } }); dialogContainer = dialog.children(".dialog-form"); exportNodesDialog = ''+ '' ; importNodesDialog = ''+ ''; } var validateExportFilenameTimeout function validateExportFilename() { if (validateExportFilenameTimeout) { clearTimeout(validateExportFilenameTimeout); } validateExportFilenameTimeout = setTimeout(function() { var filenameInput = $("#clipboard-dialog-tab-library-name"); var filename = filenameInput.val().trim(); var valid = filename.length > 0 && !/[\/\\]/.test(filename); if (valid) { filenameInput.removeClass("input-error"); $("#clipboard-dialog-export").button("enable"); } else { filenameInput.addClass("input-error"); $("#clipboard-dialog-export").button("disable"); } },100); } var validateImportTimeout; function validateImport() { if (activeTab === "clipboard-dialog-import-tab-clipboard") { if (validateImportTimeout) { clearTimeout(validateImportTimeout); } validateImportTimeout = setTimeout(function() { var importInput = $("#clipboard-import"); var v = importInput.val().trim(); if (v === "") { popover.close(true); currentPopoverError = null; importInput.removeClass("input-error"); $("#clipboard-dialog-ok").button("disable"); return; } try { if (!/^\[[\s\S]*\]$/m.test(v)) { throw new Error(RED._("clipboard.import.errors.notArray")); } var res = JSON.parse(v); for (var i=0;i').appendTo(parseError);
$('').text(v.substring(errorPos-12,errorPos)).appendTo(code)
$('').text(v.charAt(errorPos)).appendTo(code);
$('').text(v.substring(errorPos+1,errorPos+12)).appendTo(code);
}
popover.close(true).setContent(message).open();
currentPopoverError = errString;
}
} else {
currentPopoverError = null;
}
$("#clipboard-dialog-ok").button("disable");
}
},100);
} else {
var file = libraryBrowser.getSelected();
if (file && file.label && !file.children) {
$("#clipboard-dialog-ok").button("enable");
} else {
$("#clipboard-dialog-ok").button("disable");
}
}
}
function importNodes(mode) {
if (disabled) {
return;
}
mode = mode || "clipboard";
dialogContainer.empty();
dialogContainer.append($(importNodesDialog));
var tabs = RED.tabs.create({
id: "clipboard-dialog-import-tabs",
vertical: true,
onchange: function(tab) {
$("#clipboard-dialog-import-tabs-content").children().hide();
$("#" + tab.id).show();
activeTab = tab.id;
if (popover) {
popover.close(true);
currentPopoverError = null;
}
if (tab.id === "clipboard-dialog-import-tab-clipboard") {
$("#clipboard-import").focus();
} else {
libraryBrowser.focus();
}
validateImport();
}
});
tabs.addTab({
id: "clipboard-dialog-import-tab-clipboard",
label: RED._("clipboard.clipboard")
});
tabs.addTab({
id: "clipboard-dialog-import-tab-library",
label: RED._("library.library")
});
tabs.activateTab("clipboard-dialog-import-tab-"+mode);
if (mode === 'clipboard') {
setTimeout(function() {
$("#clipboard-import").focus();
},100)
}
$("#clipboard-dialog-tab-library-name").keyup(validateExportFilename);
$("#clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#clipboard-dialog-export").button("enable");
libraryBrowser = RED.library.createBrowser({
container: $("#clipboard-dialog-import-tab-library-browser"),
onselect: function(file) {
if (file && file.label && !file.children) {
$("#clipboard-dialog-ok").button("enable");
} else {
$("#clipboard-dialog-ok").button("disable");
}
}
})
loadFlowLibrary(libraryBrowser,true);
dialogContainer.i18n();
$("#clipboard-dialog-ok").show();
$("#clipboard-dialog-cancel").show();
$("#clipboard-dialog-export").hide();
$("#clipboard-dialog-download").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');
});
$("#import-file-upload").change(function() {
var fileReader = new FileReader();
fileReader.onload = function () {
$("#clipboard-import").val(fileReader.result);
validateImport();
};
fileReader.readAsText($(this).prop('files')[0]);
})
$("#import-file-upload-btn").click(function(evt) {
evt.preventDefault();
$("#import-file-upload").click();
})
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
popover = RED.popover.create({
target: $("#clipboard-import"),
trigger: "manual",
direction: "bottom",
content: ""
});
}
function exportNodes(mode) {
if (disabled) {
return;
}
mode = mode || "clipboard";
dialogContainer.empty();
dialogContainer.append($(exportNodesDialog));
var tabs = RED.tabs.create({
id: "clipboard-dialog-export-tabs",
vertical: true,
onchange: function(tab) {
$("#clipboard-dialog-export-tabs-content").children().hide();
$("#" + tab.id).show();
activeTab = tab.id;
if (tab.id === "clipboard-dialog-export-tab-clipboard") {
$("#clipboard-dialog-export").button("option","label", RED._("clipboard.export.copy"))
$("#clipboard-dialog-download").show();
} else {
$("#clipboard-dialog-export").button("option","label", RED._("clipboard.export.export"))
$("#clipboard-dialog-download").hide();
libraryBrowser.focus();
}
}
});
tabs.addTab({
id: "clipboard-dialog-export-tab-clipboard",
label: RED._("clipboard.clipboard")
});
tabs.addTab({
id: "clipboard-dialog-export-tab-library",
label: RED._("library.library")
});
tabs.activateTab("clipboard-dialog-export-tab-"+mode);
$("#clipboard-dialog-tab-library-name").keyup(validateExportFilename);
$("#clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#clipboard-dialog-export").button("enable");
libraryBrowser = RED.library.createBrowser({
container: $("#clipboard-dialog-export-tab-library-browser"),
folderTools: true,
onselect: function(file) {
if (file && file.label && !file.children) {
$("#clipboard-dialog-tab-library-name").val(file.label);
}
}
})
loadFlowLibrary(libraryBrowser,false);
$("#clipboard-dialog-tab-library-name").val("flows.json").select();
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);
setTimeout(function() { $("#clipboard-export").scrollTop(0); },50);
$("#clipboard-export").focus();
}
});
$("#export-range-group > a").click(function(evt) {
evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
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.workspaces.selection();
if (selection.length > 0) {
nodes = [];
selection.forEach(function(n) {
nodes.push(n);
nodes = nodes.concat(RED.nodes.filterNodes({z:n.id}));
});
} else {
nodes = RED.view.selection().nodes||[];
}
// Don't include the subflow meta-port nodes in the exported selection
nodes = RED.nodes.createExportableNodeSet(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);
setTimeout(function() { $("#clipboard-export").scrollTop(0); },50);
$("#clipboard-export").focus();
})
$("#clipboard-dialog-ok").hide();
$("#clipboard-dialog-cancel").hide();
$("#clipboard-dialog-export").hide();
var selection = RED.workspaces.selection();
if (selection.length > 0) {
$("#export-range-selected").click();
} else {
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();
}
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
$("#clipboard-export").focus();
$("#clipboard-dialog-cancel").show();
$("#clipboard-dialog-export").show();
$("#clipboard-dialog-download").show();
}
function loadFlowLibrary(browser,includeExamples) {
var listing = [];
if (includeExamples) {
listing.push({
library: "_examples_",
type: "flows",
icon: 'fa fa-hdd-o',
label: RED._("library.types.examples"),
path: "",
children: function(item,done) {
RED.library.loadLibraryFolder("_examples_","flows","",function(children) {
item.children = children;
done(children);
})
}
})
}
listing.push({
library: "local",
type: "flows",
icon: 'fa fa-hdd-o',
label: RED._("library.types.local"),
path: "",
expanded: true,
children: function(item,done) {
RED.library.loadLibraryFolder("local","flows","",function(children) {
item.children = children;
done(children);
})
}
})
browser.data(listing);
}
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();
$('').appendTo("body");
RED.actions.add("core:show-export-dialog",exportNodes);
RED.actions.add("core:show-import-dialog",importNodes);
RED.actions.add("core:library-export",function() { exportNodes('library') });
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
}
})();