mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Move external drag/drop to clipboard module
This commit is contained in:
parent
1c2be579d9
commit
42730b8fce
@ -499,282 +499,277 @@ RED.nodes = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function importNodes(newNodesObj,createNewIds) {
|
function importNodes(newNodesObj,createNewIds) {
|
||||||
try {
|
var i;
|
||||||
var i;
|
var n;
|
||||||
var n;
|
var newNodes;
|
||||||
var newNodes;
|
if (typeof newNodesObj === "string") {
|
||||||
if (typeof newNodesObj === "string") {
|
if (newNodesObj === "") {
|
||||||
if (newNodesObj === "") {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
try {
|
||||||
newNodes = JSON.parse(newNodesObj);
|
newNodes = JSON.parse(newNodesObj);
|
||||||
|
} catch(err) {
|
||||||
|
var e = new Error("Invalid flow: "+err.message);
|
||||||
|
e.code = "NODE_RED";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newNodes = newNodesObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$.isArray(newNodes)) {
|
||||||
|
newNodes = [newNodes];
|
||||||
|
}
|
||||||
|
var unknownTypes = [];
|
||||||
|
for (i=0;i<newNodes.length;i++) {
|
||||||
|
n = newNodes[i];
|
||||||
|
// TODO: remove workspace in next release+1
|
||||||
|
if (n.type != "workspace" &&
|
||||||
|
n.type != "tab" &&
|
||||||
|
n.type != "subflow" &&
|
||||||
|
!registry.getNodeType(n.type) &&
|
||||||
|
n.type.substring(0,8) != "subflow:") {
|
||||||
|
// TODO: get this UI thing out of here! (see below as well)
|
||||||
|
|
||||||
|
if (unknownTypes.indexOf(n.type)==-1) {
|
||||||
|
unknownTypes.push(n.type);
|
||||||
|
}
|
||||||
|
//if (n.x == null && n.y == null) {
|
||||||
|
// // config node - remove it
|
||||||
|
// newNodes.splice(i,1);
|
||||||
|
// i--;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unknownTypes.length > 0) {
|
||||||
|
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
|
||||||
|
var type = "type"+(unknownTypes.length > 1?"s":"");
|
||||||
|
RED.notify("<strong>Imported unrecognised "+type+":</strong>"+typeList,"error",false,10000);
|
||||||
|
//"DO NOT DEPLOY while in this state.<br/>Either, add missing types to Node-RED, restart and then reload page,<br/>or delete unknown "+n.name+", rewire as required, and then deploy.","error");
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeWorkspace = RED.workspaces.active();
|
||||||
|
var activeSubflow = getSubflow(activeWorkspace);
|
||||||
|
if (activeSubflow) {
|
||||||
|
for (i=0;i<newNodes.length;i++) {
|
||||||
|
var m = /^subflow:(.+)$/.exec(newNodes[i].type);
|
||||||
|
if (m) {
|
||||||
|
var subflowId = m[1];
|
||||||
|
var err;
|
||||||
|
if (subflowId === activeSubflow.id) {
|
||||||
|
err = new Error("Cannot add subflow to itself");
|
||||||
|
}
|
||||||
|
if (subflowContains(m[1],activeSubflow.id)) {
|
||||||
|
err = new Error("Cannot add subflow - circular reference detected");
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
// TODO: standardise error codes
|
||||||
|
err.code = "NODE_RED";
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var new_workspaces = [];
|
||||||
|
var workspace_map = {};
|
||||||
|
var new_subflows = [];
|
||||||
|
var subflow_map = {};
|
||||||
|
var nid;
|
||||||
|
var def;
|
||||||
|
for (i=0;i<newNodes.length;i++) {
|
||||||
|
n = newNodes[i];
|
||||||
|
// TODO: remove workspace in next release+1
|
||||||
|
if (n.type === "workspace" || n.type === "tab") {
|
||||||
|
if (n.type === "workspace") {
|
||||||
|
n.type = "tab";
|
||||||
|
}
|
||||||
|
if (defaultWorkspace == null) {
|
||||||
|
defaultWorkspace = n;
|
||||||
|
}
|
||||||
|
if (createNewIds) {
|
||||||
|
nid = getID();
|
||||||
|
workspace_map[n.id] = nid;
|
||||||
|
n.id = nid;
|
||||||
|
}
|
||||||
|
addWorkspace(n);
|
||||||
|
RED.workspaces.add(n);
|
||||||
|
new_workspaces.push(n);
|
||||||
|
} else if (n.type === "subflow") {
|
||||||
|
subflow_map[n.id] = n;
|
||||||
|
if (createNewIds) {
|
||||||
|
nid = getID();
|
||||||
|
n.id = nid;
|
||||||
|
}
|
||||||
|
// TODO: handle createNewIds - map old to new subflow ids
|
||||||
|
n.in.forEach(function(input,i) {
|
||||||
|
input.type = "subflow";
|
||||||
|
input.direction = "in";
|
||||||
|
input.z = n.id;
|
||||||
|
input.i = i;
|
||||||
|
input.id = getID();
|
||||||
|
});
|
||||||
|
n.out.forEach(function(output,i) {
|
||||||
|
output.type = "subflow";
|
||||||
|
output.direction = "out";
|
||||||
|
output.z = n.id;
|
||||||
|
output.i = i;
|
||||||
|
output.id = getID();
|
||||||
|
});
|
||||||
|
new_subflows.push(n);
|
||||||
|
addSubflow(n);
|
||||||
} else {
|
} else {
|
||||||
newNodes = newNodesObj;
|
def = registry.getNodeType(n.type);
|
||||||
}
|
if (def && def.category == "config") {
|
||||||
|
if (!RED.nodes.node(n.id)) {
|
||||||
if (!$.isArray(newNodes)) {
|
var configNode = {id:n.id,type:n.type,users:[]};
|
||||||
newNodes = [newNodes];
|
for (var d in def.defaults) {
|
||||||
}
|
if (def.defaults.hasOwnProperty(d)) {
|
||||||
var unknownTypes = [];
|
configNode[d] = n[d];
|
||||||
for (i=0;i<newNodes.length;i++) {
|
|
||||||
n = newNodes[i];
|
|
||||||
// TODO: remove workspace in next release+1
|
|
||||||
if (n.type != "workspace" &&
|
|
||||||
n.type != "tab" &&
|
|
||||||
n.type != "subflow" &&
|
|
||||||
!registry.getNodeType(n.type) &&
|
|
||||||
n.type.substring(0,8) != "subflow:") {
|
|
||||||
// TODO: get this UI thing out of here! (see below as well)
|
|
||||||
|
|
||||||
if (unknownTypes.indexOf(n.type)==-1) {
|
|
||||||
unknownTypes.push(n.type);
|
|
||||||
}
|
|
||||||
//if (n.x == null && n.y == null) {
|
|
||||||
// // config node - remove it
|
|
||||||
// newNodes.splice(i,1);
|
|
||||||
// i--;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (unknownTypes.length > 0) {
|
|
||||||
var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>";
|
|
||||||
var type = "type"+(unknownTypes.length > 1?"s":"");
|
|
||||||
RED.notify("<strong>Imported unrecognised "+type+":</strong>"+typeList,"error",false,10000);
|
|
||||||
//"DO NOT DEPLOY while in this state.<br/>Either, add missing types to Node-RED, restart and then reload page,<br/>or delete unknown "+n.name+", rewire as required, and then deploy.","error");
|
|
||||||
}
|
|
||||||
|
|
||||||
var activeWorkspace = RED.workspaces.active();
|
|
||||||
var activeSubflow = getSubflow(activeWorkspace);
|
|
||||||
if (activeSubflow) {
|
|
||||||
for (i=0;i<newNodes.length;i++) {
|
|
||||||
var m = /^subflow:(.+)$/.exec(newNodes[i].type);
|
|
||||||
if (m) {
|
|
||||||
var subflowId = m[1];
|
|
||||||
var err;
|
|
||||||
if (subflowId === activeSubflow.id) {
|
|
||||||
err = new Error("Cannot add subflow to itself");
|
|
||||||
}
|
|
||||||
if (subflowContains(m[1],activeSubflow.id)) {
|
|
||||||
err = new Error("Cannot add subflow - circular reference detected");
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
// TODO: standardise error codes
|
|
||||||
err.code = "NODE_RED";
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var new_workspaces = [];
|
|
||||||
var workspace_map = {};
|
|
||||||
var new_subflows = [];
|
|
||||||
var subflow_map = {};
|
|
||||||
var nid;
|
|
||||||
var def;
|
|
||||||
for (i=0;i<newNodes.length;i++) {
|
|
||||||
n = newNodes[i];
|
|
||||||
// TODO: remove workspace in next release+1
|
|
||||||
if (n.type === "workspace" || n.type === "tab") {
|
|
||||||
if (n.type === "workspace") {
|
|
||||||
n.type = "tab";
|
|
||||||
}
|
|
||||||
if (defaultWorkspace == null) {
|
|
||||||
defaultWorkspace = n;
|
|
||||||
}
|
|
||||||
if (createNewIds) {
|
|
||||||
nid = getID();
|
|
||||||
workspace_map[n.id] = nid;
|
|
||||||
n.id = nid;
|
|
||||||
}
|
|
||||||
addWorkspace(n);
|
|
||||||
RED.workspaces.add(n);
|
|
||||||
new_workspaces.push(n);
|
|
||||||
} else if (n.type === "subflow") {
|
|
||||||
subflow_map[n.id] = n;
|
|
||||||
if (createNewIds) {
|
|
||||||
nid = getID();
|
|
||||||
n.id = nid;
|
|
||||||
}
|
|
||||||
// TODO: handle createNewIds - map old to new subflow ids
|
|
||||||
n.in.forEach(function(input,i) {
|
|
||||||
input.type = "subflow";
|
|
||||||
input.direction = "in";
|
|
||||||
input.z = n.id;
|
|
||||||
input.i = i;
|
|
||||||
input.id = getID();
|
|
||||||
});
|
|
||||||
n.out.forEach(function(output,i) {
|
|
||||||
output.type = "subflow";
|
|
||||||
output.direction = "out";
|
|
||||||
output.z = n.id;
|
|
||||||
output.i = i;
|
|
||||||
output.id = getID();
|
|
||||||
});
|
|
||||||
new_subflows.push(n);
|
|
||||||
addSubflow(n);
|
|
||||||
} else {
|
|
||||||
def = registry.getNodeType(n.type);
|
|
||||||
if (def && def.category == "config") {
|
|
||||||
if (!RED.nodes.node(n.id)) {
|
|
||||||
var configNode = {id:n.id,type:n.type,users:[]};
|
|
||||||
for (var d in def.defaults) {
|
|
||||||
if (def.defaults.hasOwnProperty(d)) {
|
|
||||||
configNode[d] = n[d];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
configNode.label = def.label;
|
|
||||||
configNode._def = def;
|
|
||||||
RED.nodes.add(configNode);
|
|
||||||
}
|
}
|
||||||
|
configNode.label = def.label;
|
||||||
|
configNode._def = def;
|
||||||
|
RED.nodes.add(configNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (defaultWorkspace == null) {
|
}
|
||||||
defaultWorkspace = { type:"tab", id:getID(), label:"Sheet 1" };
|
if (defaultWorkspace == null) {
|
||||||
addWorkspace(defaultWorkspace);
|
defaultWorkspace = { type:"tab", id:getID(), label:"Sheet 1" };
|
||||||
RED.workspaces.add(defaultWorkspace);
|
addWorkspace(defaultWorkspace);
|
||||||
new_workspaces.push(defaultWorkspace);
|
RED.workspaces.add(defaultWorkspace);
|
||||||
activeWorkspace = RED.workspaces.active();
|
new_workspaces.push(defaultWorkspace);
|
||||||
}
|
activeWorkspace = RED.workspaces.active();
|
||||||
|
}
|
||||||
|
|
||||||
var node_map = {};
|
var node_map = {};
|
||||||
var new_nodes = [];
|
var new_nodes = [];
|
||||||
var new_links = [];
|
var new_links = [];
|
||||||
|
|
||||||
for (i=0;i<newNodes.length;i++) {
|
for (i=0;i<newNodes.length;i++) {
|
||||||
n = newNodes[i];
|
n = newNodes[i];
|
||||||
// TODO: remove workspace in next release+1
|
// TODO: remove workspace in next release+1
|
||||||
if (n.type !== "workspace" && n.type !== "tab" && n.type !== "subflow") {
|
if (n.type !== "workspace" && n.type !== "tab" && n.type !== "subflow") {
|
||||||
def = registry.getNodeType(n.type);
|
def = registry.getNodeType(n.type);
|
||||||
if (!def || def.category != "config") {
|
if (!def || def.category != "config") {
|
||||||
var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false};
|
var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false};
|
||||||
if (createNewIds) {
|
if (createNewIds) {
|
||||||
if (subflow_map[node.z]) {
|
if (subflow_map[node.z]) {
|
||||||
node.z = subflow_map[node.z].id;
|
node.z = subflow_map[node.z].id;
|
||||||
} else {
|
|
||||||
node.z = workspace_map[node.z];
|
|
||||||
if (!workspaces[node.z]) {
|
|
||||||
node.z = activeWorkspace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node.id = getID();
|
|
||||||
} else {
|
} else {
|
||||||
node.id = n.id;
|
node.z = workspace_map[node.z];
|
||||||
if (node.z == null || (!workspaces[node.z] && !subflow_map[node.z])) {
|
if (!workspaces[node.z]) {
|
||||||
node.z = activeWorkspace;
|
node.z = activeWorkspace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.type = n.type;
|
node.id = getID();
|
||||||
node._def = def;
|
} else {
|
||||||
if (n.type.substring(0,7) === "subflow") {
|
node.id = n.id;
|
||||||
var parentId = n.type.split(":")[1];
|
if (node.z == null || (!workspaces[node.z] && !subflow_map[node.z])) {
|
||||||
var subflow = subflow_map[parentId]||getSubflow(parentId);
|
node.z = activeWorkspace;
|
||||||
if (createNewIds) {
|
}
|
||||||
parentId = subflow.id;
|
}
|
||||||
node.type = "subflow:"+parentId;
|
node.type = n.type;
|
||||||
node._def = registry.getNodeType(node.type);
|
node._def = def;
|
||||||
delete node.i;
|
if (n.type.substring(0,7) === "subflow") {
|
||||||
}
|
var parentId = n.type.split(":")[1];
|
||||||
node.name = n.name;
|
var subflow = subflow_map[parentId]||getSubflow(parentId);
|
||||||
node.outputs = subflow.out.length;
|
if (createNewIds) {
|
||||||
node.inputs = subflow.in.length;
|
parentId = subflow.id;
|
||||||
} else {
|
node.type = "subflow:"+parentId;
|
||||||
if (!node._def) {
|
node._def = registry.getNodeType(node.type);
|
||||||
if (node.x && node.y) {
|
delete node.i;
|
||||||
node._def = {
|
}
|
||||||
color:"#fee",
|
node.name = n.name;
|
||||||
defaults: {},
|
node.outputs = subflow.out.length;
|
||||||
label: "unknown: "+n.type,
|
node.inputs = subflow.in.length;
|
||||||
labelStyle: "node_label_italic",
|
} else {
|
||||||
outputs: n.outputs||n.wires.length
|
if (!node._def) {
|
||||||
}
|
if (node.x && node.y) {
|
||||||
} else {
|
node._def = {
|
||||||
node._def = {
|
color:"#fee",
|
||||||
category:"config"
|
defaults: {},
|
||||||
};
|
label: "unknown: "+n.type,
|
||||||
node.users = [];
|
labelStyle: "node_label_italic",
|
||||||
}
|
outputs: n.outputs||n.wires.length
|
||||||
var orig = {};
|
}
|
||||||
for (var p in n) {
|
} else {
|
||||||
if (n.hasOwnProperty(p) && p!="x" && p!="y" && p!="z" && p!="id" && p!="wires") {
|
node._def = {
|
||||||
orig[p] = n[p];
|
category:"config"
|
||||||
}
|
};
|
||||||
}
|
node.users = [];
|
||||||
node._orig = orig;
|
}
|
||||||
node.name = n.type;
|
var orig = {};
|
||||||
node.type = "unknown";
|
for (var p in n) {
|
||||||
}
|
if (n.hasOwnProperty(p) && p!="x" && p!="y" && p!="z" && p!="id" && p!="wires") {
|
||||||
if (node._def.category != "config") {
|
orig[p] = n[p];
|
||||||
node.inputs = n.inputs||node._def.inputs;
|
}
|
||||||
node.outputs = n.outputs||node._def.outputs;
|
}
|
||||||
for (var d2 in node._def.defaults) {
|
node._orig = orig;
|
||||||
if (node._def.defaults.hasOwnProperty(d2)) {
|
node.name = n.type;
|
||||||
node[d2] = n[d2];
|
node.type = "unknown";
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
addNode(node);
|
|
||||||
RED.editor.validateNode(node);
|
|
||||||
node_map[n.id] = node;
|
|
||||||
if (node._def.category != "config") {
|
if (node._def.category != "config") {
|
||||||
new_nodes.push(node);
|
node.inputs = n.inputs||node._def.inputs;
|
||||||
|
node.outputs = n.outputs||node._def.outputs;
|
||||||
|
for (var d2 in node._def.defaults) {
|
||||||
|
if (node._def.defaults.hasOwnProperty(d2)) {
|
||||||
|
node[d2] = n[d2];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
addNode(node);
|
||||||
|
RED.editor.validateNode(node);
|
||||||
|
node_map[n.id] = node;
|
||||||
|
if (node._def.category != "config") {
|
||||||
|
new_nodes.push(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i=0;i<new_nodes.length;i++) {
|
}
|
||||||
n = new_nodes[i];
|
for (i=0;i<new_nodes.length;i++) {
|
||||||
for (var w1=0;w1<n.wires.length;w1++) {
|
n = new_nodes[i];
|
||||||
var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]];
|
for (var w1=0;w1<n.wires.length;w1++) {
|
||||||
for (var w2=0;w2<wires.length;w2++) {
|
var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]];
|
||||||
if (wires[w2] in node_map) {
|
for (var w2=0;w2<wires.length;w2++) {
|
||||||
var link = {source:n,sourcePort:w1,target:node_map[wires[w2]]};
|
if (wires[w2] in node_map) {
|
||||||
addLink(link);
|
var link = {source:n,sourcePort:w1,target:node_map[wires[w2]]};
|
||||||
new_links.push(link);
|
addLink(link);
|
||||||
}
|
new_links.push(link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete n.wires;
|
|
||||||
}
|
}
|
||||||
for (i=0;i<new_subflows.length;i++) {
|
delete n.wires;
|
||||||
n = new_subflows[i];
|
}
|
||||||
n.in.forEach(function(input) {
|
for (i=0;i<new_subflows.length;i++) {
|
||||||
input.wires.forEach(function(wire) {
|
n = new_subflows[i];
|
||||||
var link = {source:input, sourcePort:0, target:node_map[wire.id]};
|
n.in.forEach(function(input) {
|
||||||
addLink(link);
|
input.wires.forEach(function(wire) {
|
||||||
new_links.push(link);
|
var link = {source:input, sourcePort:0, target:node_map[wire.id]};
|
||||||
});
|
addLink(link);
|
||||||
delete input.wires;
|
new_links.push(link);
|
||||||
});
|
});
|
||||||
n.out.forEach(function(output) {
|
delete input.wires;
|
||||||
output.wires.forEach(function(wire) {
|
});
|
||||||
var link;
|
n.out.forEach(function(output) {
|
||||||
if (wire.id == n.id) {
|
output.wires.forEach(function(wire) {
|
||||||
link = {source:n.in[wire.port], sourcePort:wire.port,target:output};
|
var link;
|
||||||
} else {
|
if (wire.id == n.id) {
|
||||||
link = {source:node_map[wire.id], sourcePort:wire.port,target:output};
|
link = {source:n.in[wire.port], sourcePort:wire.port,target:output};
|
||||||
}
|
} else {
|
||||||
addLink(link);
|
link = {source:node_map[wire.id], sourcePort:wire.port,target:output};
|
||||||
new_links.push(link);
|
}
|
||||||
});
|
addLink(link);
|
||||||
delete output.wires;
|
new_links.push(link);
|
||||||
});
|
});
|
||||||
}
|
delete output.wires;
|
||||||
|
});
|
||||||
return [new_nodes,new_links,new_workspaces,new_subflows];
|
|
||||||
} catch(error) {
|
|
||||||
if (error.code != "NODE_RED") {
|
|
||||||
console.log(error.stack);
|
|
||||||
RED.notify("<strong>Error</strong>: "+error,"error");
|
|
||||||
} else {
|
|
||||||
RED.notify("<strong>Error</strong>: "+error.message,"error");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [new_nodes,new_links,new_workspaces,new_subflows];
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -120,6 +120,11 @@ RED.clipboard = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hideDropTarget() {
|
||||||
|
$("#dropTarget").hide();
|
||||||
|
RED.keyboard.remove(/* ESCAPE */ 27);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
RED.view.on("selection-changed",function(selection) {
|
RED.view.on("selection-changed",function(selection) {
|
||||||
@ -135,6 +140,32 @@ RED.clipboard = (function() {
|
|||||||
});
|
});
|
||||||
RED.keyboard.add(/* e */ 69,{ctrl:true},function(){exportNodes();d3.event.preventDefault();});
|
RED.keyboard.add(/* e */ 69,{ctrl:true},function(){exportNodes();d3.event.preventDefault();});
|
||||||
RED.keyboard.add(/* i */ 73,{ctrl:true},function(){importNodes();d3.event.preventDefault();});
|
RED.keyboard.add(/* i */ 73,{ctrl:true},function(){importNodes();d3.event.preventDefault();});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$('#chart').on("dragenter",function(event) {
|
||||||
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||||
|
$("#dropTarget").css({display:'table'});
|
||||||
|
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#dropTarget').on("dragover",function(event) {
|
||||||
|
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("dragleave",function(event) {
|
||||||
|
hideDropTarget();
|
||||||
|
})
|
||||||
|
.on("drop",function(event) {
|
||||||
|
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||||
|
hideDropTarget();
|
||||||
|
RED.view.importNodes(data);
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
import: importNodes,
|
import: importNodes,
|
||||||
export: exportNodes
|
export: exportNodes
|
||||||
|
@ -282,8 +282,100 @@ RED.view = (function() {
|
|||||||
updateSelection();
|
updateSelection();
|
||||||
updateActiveNodes();
|
updateActiveNodes();
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#btn-zoom-out').click(function() {zoomOut();});
|
||||||
|
$('#btn-zoom-zero').click(function() {zoomZero();});
|
||||||
|
$('#btn-zoom-in').click(function() {zoomIn();});
|
||||||
|
$("#chart").on('DOMMouseScroll mousewheel', function (evt) {
|
||||||
|
if ( evt.altKey ) {
|
||||||
|
evt.preventDefault();
|
||||||
|
evt.stopPropagation();
|
||||||
|
var move = -(evt.originalEvent.detail) || evt.originalEvent.wheelDelta;
|
||||||
|
if (move <= 0) { zoomOut(); }
|
||||||
|
else { zoomIn(); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle nodes dragged from the palette
|
||||||
|
$("#chart").droppable({
|
||||||
|
accept:".palette_node",
|
||||||
|
drop: function( event, ui ) {
|
||||||
|
d3.event = event;
|
||||||
|
var selected_tool = ui.draggable[0].type;
|
||||||
|
|
||||||
|
var m = /^subflow:(.+)$/.exec(selected_tool);
|
||||||
|
|
||||||
|
if (activeSubflow && m) {
|
||||||
|
var subflowId = m[1];
|
||||||
|
if (subflowId === activeSubflow.id) {
|
||||||
|
RED.notify("<strong>Error</strong>: Cannot add subflow to itself","error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (RED.nodes.subflowContains(m[1],activeSubflow.id)) {
|
||||||
|
RED.notify("<strong>Error</strong>: Cannot add subflow - circular reference detected","error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var mousePos = d3.touches(this)[0]||d3.mouse(this);
|
||||||
|
mousePos[1] += this.scrollTop;
|
||||||
|
mousePos[0] += this.scrollLeft;
|
||||||
|
mousePos[1] /= scaleFactor;
|
||||||
|
mousePos[0] /= scaleFactor;
|
||||||
|
|
||||||
|
var nn = { id:(1+Math.random()*4294967295).toString(16),x: mousePos[0],y:mousePos[1],w:node_width,z:RED.workspaces.active()};
|
||||||
|
|
||||||
|
nn.type = selected_tool;
|
||||||
|
nn._def = RED.nodes.getType(nn.type);
|
||||||
|
|
||||||
|
if (!m) {
|
||||||
|
nn.inputs = nn._def.inputs || 0;
|
||||||
|
nn.outputs = nn._def.outputs;
|
||||||
|
nn.changed = true;
|
||||||
|
|
||||||
|
for (var d in nn._def.defaults) {
|
||||||
|
if (nn._def.defaults.hasOwnProperty(d)) {
|
||||||
|
nn[d] = nn._def.defaults[d].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nn._def.onadd) {
|
||||||
|
nn._def.onadd.call(nn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var subflow = RED.nodes.subflow(m[1]);
|
||||||
|
nn.inputs = subflow.in.length;
|
||||||
|
nn.outputs = subflow.out.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn.h = Math.max(node_height,(nn.outputs||0) * 15);
|
||||||
|
RED.history.push({t:'add',nodes:[nn.id],dirty:dirty});
|
||||||
|
RED.nodes.add(nn);
|
||||||
|
RED.editor.validateNode(nn);
|
||||||
|
setDirty(true);
|
||||||
|
// auto select dropped node - so info shows (if visible)
|
||||||
|
clearSelection();
|
||||||
|
nn.selected = true;
|
||||||
|
moving_set.push({n:nn});
|
||||||
|
updateActiveNodes();
|
||||||
|
updateSelection();
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
if (nn._def.autoedit) {
|
||||||
|
RED.editor.edit(nn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.keyboard.add(/* z */ 90,{ctrl:true},function(){RED.history.pop();});
|
||||||
|
RED.keyboard.add(/* a */ 65,{ctrl:true},function(){selectAll();d3.event.preventDefault();});
|
||||||
|
RED.keyboard.add(/* = */ 187,{ctrl:true},function(){zoomIn();d3.event.preventDefault();});
|
||||||
|
RED.keyboard.add(/* - */ 189,{ctrl:true},function(){zoomOut();d3.event.preventDefault();});
|
||||||
|
RED.keyboard.add(/* 0 */ 48,{ctrl:true},function(){zoomZero();d3.event.preventDefault();});
|
||||||
|
RED.keyboard.add(/* v */ 86,{ctrl:true},function(){importNodes(clipboard);d3.event.preventDefault();});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function canvasMouseDown() {
|
function canvasMouseDown() {
|
||||||
@ -517,90 +609,6 @@ RED.view = (function() {
|
|||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#btn-zoom-out').click(function() {zoomOut();});
|
|
||||||
$('#btn-zoom-zero').click(function() {zoomZero();});
|
|
||||||
$('#btn-zoom-in').click(function() {zoomIn();});
|
|
||||||
$("#chart").on('DOMMouseScroll mousewheel', function (evt) {
|
|
||||||
if ( evt.altKey ) {
|
|
||||||
evt.preventDefault();
|
|
||||||
evt.stopPropagation();
|
|
||||||
var move = -(evt.originalEvent.detail) || evt.originalEvent.wheelDelta;
|
|
||||||
if (move <= 0) { zoomOut(); }
|
|
||||||
else { zoomIn(); }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#chart").droppable({
|
|
||||||
accept:".palette_node",
|
|
||||||
drop: function( event, ui ) {
|
|
||||||
d3.event = event;
|
|
||||||
var selected_tool = ui.draggable[0].type;
|
|
||||||
|
|
||||||
var m = /^subflow:(.+)$/.exec(selected_tool);
|
|
||||||
|
|
||||||
if (activeSubflow && m) {
|
|
||||||
var subflowId = m[1];
|
|
||||||
if (subflowId === activeSubflow.id) {
|
|
||||||
RED.notify("<strong>Error</strong>: Cannot add subflow to itself","error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (RED.nodes.subflowContains(m[1],activeSubflow.id)) {
|
|
||||||
RED.notify("<strong>Error</strong>: Cannot add subflow - circular reference detected","error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var mousePos = d3.touches(this)[0]||d3.mouse(this);
|
|
||||||
mousePos[1] += this.scrollTop;
|
|
||||||
mousePos[0] += this.scrollLeft;
|
|
||||||
mousePos[1] /= scaleFactor;
|
|
||||||
mousePos[0] /= scaleFactor;
|
|
||||||
|
|
||||||
var nn = { id:(1+Math.random()*4294967295).toString(16),x: mousePos[0],y:mousePos[1],w:node_width,z:RED.workspaces.active()};
|
|
||||||
|
|
||||||
nn.type = selected_tool;
|
|
||||||
nn._def = RED.nodes.getType(nn.type);
|
|
||||||
|
|
||||||
if (!m) {
|
|
||||||
nn.inputs = nn._def.inputs || 0;
|
|
||||||
nn.outputs = nn._def.outputs;
|
|
||||||
nn.changed = true;
|
|
||||||
|
|
||||||
for (var d in nn._def.defaults) {
|
|
||||||
if (nn._def.defaults.hasOwnProperty(d)) {
|
|
||||||
nn[d] = nn._def.defaults[d].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nn._def.onadd) {
|
|
||||||
nn._def.onadd.call(nn);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var subflow = RED.nodes.subflow(m[1]);
|
|
||||||
nn.inputs = subflow.in.length;
|
|
||||||
nn.outputs = subflow.out.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
nn.h = Math.max(node_height,(nn.outputs||0) * 15);
|
|
||||||
RED.history.push({t:'add',nodes:[nn.id],dirty:dirty});
|
|
||||||
RED.nodes.add(nn);
|
|
||||||
RED.editor.validateNode(nn);
|
|
||||||
setDirty(true);
|
|
||||||
// auto select dropped node - so info shows (if visible)
|
|
||||||
clearSelection();
|
|
||||||
nn.selected = true;
|
|
||||||
moving_set.push({n:nn});
|
|
||||||
updateActiveNodes();
|
|
||||||
updateSelection();
|
|
||||||
redraw();
|
|
||||||
|
|
||||||
if (nn._def.autoedit) {
|
|
||||||
RED.editor.edit(nn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function zoomIn() {
|
function zoomIn() {
|
||||||
if (scaleFactor < 2) {
|
if (scaleFactor < 2) {
|
||||||
scaleFactor += 0.1;
|
scaleFactor += 0.1;
|
||||||
@ -1638,13 +1646,6 @@ RED.view = (function() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RED.keyboard.add(/* z */ 90,{ctrl:true},function(){RED.history.pop();});
|
|
||||||
RED.keyboard.add(/* a */ 65,{ctrl:true},function(){selectAll();d3.event.preventDefault();});
|
|
||||||
RED.keyboard.add(/* = */ 187,{ctrl:true},function(){zoomIn();d3.event.preventDefault();});
|
|
||||||
RED.keyboard.add(/* - */ 189,{ctrl:true},function(){zoomOut();d3.event.preventDefault();});
|
|
||||||
RED.keyboard.add(/* 0 */ 48,{ctrl:true},function(){zoomZero();d3.event.preventDefault();});
|
|
||||||
RED.keyboard.add(/* v */ 86,{ctrl:true},function(){importNodes(clipboard);d3.event.preventDefault();});
|
|
||||||
|
|
||||||
// TODO: 'dirty' should be a property of RED.nodes - with an event callback for ui hooks
|
// TODO: 'dirty' should be a property of RED.nodes - with an event callback for ui hooks
|
||||||
function setDirty(d) {
|
function setDirty(d) {
|
||||||
dirty = d;
|
dirty = d;
|
||||||
@ -1746,34 +1747,6 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideDropTarget() {
|
|
||||||
$("#dropTarget").hide();
|
|
||||||
RED.keyboard.remove(/* ESCAPE */ 27);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$('#chart').on("dragenter",function(event) {
|
|
||||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
|
||||||
$("#dropTarget").css({display:'table'});
|
|
||||||
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#dropTarget').on("dragover",function(event) {
|
|
||||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on("dragleave",function(event) {
|
|
||||||
hideDropTarget();
|
|
||||||
})
|
|
||||||
.on("drop",function(event) {
|
|
||||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
|
||||||
hideDropTarget();
|
|
||||||
RED.view.importNodes(data);
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: DRY
|
// TODO: DRY
|
||||||
var eventHandler = (function() {
|
var eventHandler = (function() {
|
||||||
var handlers = {};
|
var handlers = {};
|
||||||
|
Loading…
Reference in New Issue
Block a user