mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
333 lines
13 KiB
HTML
333 lines
13 KiB
HTML
<!--
|
|
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.
|
|
-->
|
|
|
|
<script type="text/x-red" data-template-name="link in">
|
|
<div class="form-row">
|
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
|
</div>
|
|
<div class="form-row node-input-link-row"></div>
|
|
</script>
|
|
<script type="text/x-red" data-template-name="link out">
|
|
<div class="form-row">
|
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
|
</div>
|
|
<div class="form-row node-input-link-row"></div>
|
|
</script>
|
|
<script type="text/x-red" data-help-name="link in">
|
|
<p>Create virtual wires between flows.</p>
|
|
<p>The node can be connected to any <b>link out</b> node that exists on any tab.
|
|
Once connected, they behave as if they were wired together.</p>
|
|
<p>The wires between link nodes are only displayed when a link node is selected.
|
|
If there are any wires to other tabs, a virtual node is show that can be clicked
|
|
on to jump to the appropriate tab.</p>
|
|
<p>Links cannot be created going into, or out of, a subflow.</p>
|
|
</script>
|
|
<script type="text/x-red" data-help-name="link out">
|
|
<p>Create virtual wires between flows.</p>
|
|
<p>The node can be connected to any <b>link in</b> node that exists on any tab.
|
|
Once connected, they behave as if they were wired together.</p>
|
|
<p>The wires between link nodes are only displayed when a link node is selected.
|
|
If there are any wires to other tabs, a virtual node is show that can be clicked
|
|
on to jump to the appropriate tab.</p>
|
|
<p>Links cannot be created going into, or out of, a subflow.</p>
|
|
</script>
|
|
<style>
|
|
#node-input-link-container {
|
|
position: relative;
|
|
}
|
|
#node-input-link-container li {
|
|
padding: 2px 5px;
|
|
background: none;
|
|
font-size: 0.8em;
|
|
margin:0;
|
|
white-space: nowrap;
|
|
}
|
|
#node-input-link-container li label {
|
|
margin-bottom: 0;
|
|
width: 100%;
|
|
}
|
|
#node-input-link-container li label input {
|
|
vertical-align: top;
|
|
width:15px;
|
|
margin-right: 10px;
|
|
}
|
|
#node-input-link-container li:hover,
|
|
#node-input-link-container li:hover .node-input-target-node-sublabel {
|
|
background: #f0f0f0;
|
|
}
|
|
.node-input-link-node-sublabel {
|
|
position:absolute;
|
|
right: 0px;
|
|
padding-right: 10px;
|
|
padding-left: 10px;
|
|
font-size: 0.8em;
|
|
}
|
|
</style>
|
|
|
|
<script type="text/javascript">
|
|
(function() {
|
|
|
|
function sortNodeList(nodeList,sortOn,sortOnSecond) {
|
|
var currentSort = nodeList.data('currentSort');
|
|
var currentSortOrder = nodeList.data('currentSortOrder');
|
|
|
|
if (!currentSort) {
|
|
currentSort = sortOn;
|
|
currentSortOrder = 'a';
|
|
} else {
|
|
if (currentSort === sortOn) {
|
|
currentSortOrder = (currentSortOrder === 'a'?'d':'a');
|
|
} else {
|
|
currentSortOrder = 'a';
|
|
}
|
|
currentSort = sortOn;
|
|
}
|
|
nodeList.data('currentSort',currentSort);
|
|
nodeList.data('currentSortOrder',currentSortOrder);
|
|
|
|
$("#node-input-link-container-div .fa").hide();
|
|
$(".node-input-link-sort-"+currentSort+"-"+currentSortOrder).show();
|
|
|
|
|
|
var items = nodeList.find("li").get();
|
|
items.sort(function(a,b) {
|
|
var labelA = $(a).find(".node-input-link-node-"+currentSort).text().toLowerCase();
|
|
var labelB = $(b).find(".node-input-link-node-"+currentSort).text().toLowerCase();
|
|
if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
|
|
if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
|
|
|
|
if (sortOnSecond) {
|
|
labelA = $(a).find(".node-input-link-node-"+sortOnSecond).text().toLowerCase();
|
|
labelB = $(b).find(".node-input-link-node-"+sortOnSecond).text().toLowerCase();
|
|
if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
|
|
if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
|
|
}
|
|
return 0;
|
|
});
|
|
$.each(items, function(i, li) {
|
|
nodeList.append(li);
|
|
});
|
|
}
|
|
function onEditPrepare(node,targetType) {
|
|
if (!node.links) {
|
|
node.links = [];
|
|
}
|
|
node.oldLinks = [];
|
|
|
|
$('<div id="node-input-link-container-div" style="min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">'+
|
|
' <div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">'+
|
|
' <div style="display: inline-block;margin-left: 5px;"><a id="node-input-link-sort-label" href="#" data-i18n="[title]link.label.sortByLabel"><span data-i18n="link.label.node">name</span> <i class="node-input-link-sort-label-a fa fa-caret-down"></i><i class="node-input-link-sort-label-d fa fa-caret-up"></i></a></div>'+
|
|
' <div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-link-sort-type" href="#" data-i18n="[title]link.label.sortByFlow"><i class="node-input-link-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-link-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="link.label.type">flow</span></a></div>'+
|
|
' </div>'+
|
|
' <div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">'+
|
|
' <ul id="node-input-link-container" style=" list-style-type:none; margin: 0;"></ul>'+
|
|
' </div>'+
|
|
'</div>').appendTo('.node-input-link-row');
|
|
|
|
var nodeList = $("#node-input-link-container");
|
|
var candidateNodes = RED.nodes.filterNodes({type:targetType});
|
|
var inSubflow = (RED.nodes.subflow(node.z) != null);
|
|
candidateNodes.forEach(function(n) {
|
|
if (inSubflow) {
|
|
if (n.z !== node.z) {
|
|
return;
|
|
}
|
|
} else {
|
|
if (RED.nodes.subflow(n.z)!=null) {
|
|
return;
|
|
}
|
|
}
|
|
var isChecked = false;
|
|
|
|
isChecked = (node.links.indexOf(n.id) !== -1) || (n.links||[]).indexOf(node.id) !== -1;
|
|
|
|
if (isChecked) {
|
|
node.oldLinks.push(n.id);
|
|
}
|
|
|
|
var container = $('<li/>',{class:"node-input-link-node"});
|
|
var row = $('<label/>',{for:"node-input-link-node-"+n.id}).appendTo(container);
|
|
$('<input>',{type:"checkbox",class:"node-input-link-node-checkbox",id:"node-input-link-node-"+n.id})
|
|
.data('node-id',n.id)
|
|
.prop('checked', isChecked)
|
|
.appendTo(row);
|
|
container.on('mouseover',function(e) {
|
|
n.highlighted = true;
|
|
n.dirty = true;
|
|
RED.view.redraw();
|
|
});
|
|
container.on('mouseout',function(e) {
|
|
n.highlighted = false;
|
|
n.dirty = true;
|
|
RED.view.redraw();
|
|
});
|
|
var labelSpan = $('<span>');
|
|
var label = n.name||n.id;
|
|
var sublabel;
|
|
var tab = RED.nodes.workspace(n.z);
|
|
if (tab) {
|
|
sublabel = tab.label||tab.id;
|
|
} else {
|
|
tab = RED.nodes.subflow(n.z);
|
|
sublabel = "subflow : "+tab.name;
|
|
}
|
|
$('<span>',{class:"node-input-link-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
|
|
if (sublabel) {
|
|
$('<span>',{class:"node-input-link-node-sublabel"}).text(sublabel).appendTo(row);
|
|
}
|
|
container.appendTo(nodeList);
|
|
});
|
|
|
|
sortNodeList(nodeList,'sublabel','label');
|
|
|
|
$("#node-input-link-sort-label").click(function(e) {
|
|
e.preventDefault();
|
|
sortNodeList(nodeList,'label');
|
|
});
|
|
|
|
$("#node-input-link-sort-type").click(function(e) {
|
|
e.preventDefault();
|
|
sortNodeList(nodeList,'sublabel');
|
|
});
|
|
}
|
|
|
|
function resizeNodeList() {
|
|
var rows = $("#dialog-form>div:not(.node-input-link-row)");
|
|
var height = $("#dialog-form").height();
|
|
for (var i=0;i<rows.size();i++) {
|
|
height -= $(rows[i]).outerHeight(true);
|
|
}
|
|
var editorRow = $("#dialog-form>div.node-input-link-row");
|
|
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
|
$("#node-input-link-container-div").css("height",height+"px");
|
|
}
|
|
|
|
function onEditSave(node) {
|
|
node.links = [];
|
|
$(".node-input-link-node-checkbox").each(function(n) {
|
|
if ($(this).prop("checked")) {
|
|
node.links.push($(this).data('node-id'));
|
|
}
|
|
})
|
|
node.oldLinks.sort();
|
|
node.links.sort();
|
|
var nodeMap = {};
|
|
var length = Math.max(node.oldLinks.length,node.links.length);
|
|
for (var i=0;i<length;i++) {
|
|
if (i<node.oldLinks.length) {
|
|
nodeMap[node.oldLinks[i]] = nodeMap[node.oldLinks[i]]||{};
|
|
nodeMap[node.oldLinks[i]].old = true;
|
|
}
|
|
if (i<node.links.length) {
|
|
nodeMap[node.links[i]] = nodeMap[node.links[i]]||{};
|
|
nodeMap[node.links[i]].new = true;
|
|
}
|
|
}
|
|
var n;
|
|
for (var id in nodeMap) {
|
|
if (nodeMap.hasOwnProperty(id)) {
|
|
n = RED.nodes.node(id);
|
|
if (n) {
|
|
if (nodeMap[id].old && !nodeMap[id].new) {
|
|
// Removed id
|
|
i = n.links.indexOf(node.id);
|
|
if (i > -1) {
|
|
n.links.splice(i,1);
|
|
}
|
|
} else if (!nodeMap[id].old && nodeMap[id].new) {
|
|
// Added id
|
|
i = n.links.indexOf(id);
|
|
if (i === -1) {
|
|
n.links.push(node.id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function onAdd() {
|
|
for (var i=0;i<this.links.length;i++) {
|
|
var n = RED.nodes.node(this.links[i]);
|
|
if (n.links.indexOf(this.id) === -1) {
|
|
n.links.push(this.id);
|
|
}
|
|
}
|
|
}
|
|
|
|
RED.nodes.registerType('link in',{
|
|
category: 'input',
|
|
color:"#ddd",//"#87D8CF",
|
|
defaults: {
|
|
name: {value:""},
|
|
links: { value: [] }
|
|
},
|
|
inputs:0,
|
|
outputs:1,
|
|
icon: "link-out.png",
|
|
outputLabels: function(i) {
|
|
return this.name||this._("link.linkIn");
|
|
},
|
|
label: function() {
|
|
return this.name||this._("link.linkIn");
|
|
},
|
|
labelStyle: function() {
|
|
return this.name?"node_label_italic":"";
|
|
},
|
|
oneditprepare: function() {
|
|
onEditPrepare(this,"link out");
|
|
},
|
|
oneditsave: function() {
|
|
onEditSave(this);
|
|
},
|
|
onadd: onAdd,
|
|
oneditresize: resizeNodeList
|
|
});
|
|
|
|
RED.nodes.registerType('link out',{
|
|
category: 'output',
|
|
color:"#ddd",//"#87D8CF",
|
|
defaults: {
|
|
name: {value:""},
|
|
links: { value: []}
|
|
},
|
|
align:"right",
|
|
inputs:1,
|
|
outputs:0,
|
|
icon: "link-out.png",
|
|
inputLabels: function(i) {
|
|
return this.name||this._("link.linkOut");
|
|
},
|
|
label: function() {
|
|
return this.name||this._("link.linkOut");
|
|
},
|
|
labelStyle: function() {
|
|
return this.name?"node_label_italic":"";
|
|
},
|
|
oneditprepare: function() {
|
|
onEditPrepare(this,"link in");
|
|
},
|
|
oneditsave: function() {
|
|
onEditSave(this);
|
|
},
|
|
onadd: onAdd,
|
|
oneditresize: resizeNodeList
|
|
});
|
|
})();
|
|
</script>
|