Skip to content

Instantly share code, notes, and snippets.

@gorenje
Created April 21, 2023 12:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gorenje/bbf6f4f27553b864a0fc4dcc63d12ae2 to your computer and use it in GitHub Desktop.
Save gorenje/bbf6f4f27553b864a0fc4dcc63d12ae2 to your computer and use it in GitHub Desktop.
Node-RED node for showing orphan nodes
<script type="text/javascript">
RED.nodes.registerType('Orphans',{
color: '#e5e4ef',
icon: "subflow.svg",
category: 'Writer Map Tools',
paletteLabel: "Orphans",
defaults: {
name: {
value:"",
},
},
inputs:0,
outputs:0,
label: function() {
return (this.name || this._def.paletteLabel);
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var node = this;
this._resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-list-row)");
var height = $("#dialog-form").height();
for (var i=0;i<rows.length;i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
var search = $("#node-input-orphan-target-filter").searchBox({
style: "compact",
delay: 300,
change: function() {
var val = $(this).val().trim().toLowerCase();
if (val === "") {
dirList.treeList("filter", null);
search.searchBox("count","");
} else {
var count = dirList.treeList("filter", function(item) {
return item.label.toLowerCase().indexOf(val) > -1 || item.node.type.toLowerCase().indexOf(val) > -1
});
search.searchBox("count",count+" / "+items.length);
}
}
});
var dirList = $("#node-input-orphan-target-container-div").css({
width: "100%",
height: "100%"
}).treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
item.node.highlighted = true;
item.node.dirty = true;
RED.view.redraw();
}).on("treelistitemmouseout", function(e, item) {
item.node.highlighted = false;
item.node.dirty = true;
RED.view.redraw();
}).on('treelistselect', function(event, item) {
if ( item.node ) {
RED.workspaces.show(item.node.z,false,false,true);
item.node.highlighted = true;
item.node.dirty = true;
RED.view.reveal(item.node.id,true)
RED.view.redraw();
}
});;
/* ***************
* code taken from
* https://discourse.nodered.org/t/search-for-orphan-nodes/77783/3
*/
const connectedNodes = new Set()
var candidateNodes = [];
// Iterate over all links, add the nodes to the 'connected' set
RED.nodes.eachLink(link => { connectedNodes.add(link.source); connectedNodes.add(link.target) })
// Iterate over all nodes, add any not in the connected set to the disconnected set
RED.nodes.eachNode(node => { if (!connectedNodes.has(node)) candidateNodes.push(node) })
/************ done code borrowing ************/
var items = [];
var nodeItemMap = {};
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
return;
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
nodeItemMap[n.id] = {
node: n,
label: label,
sublabel: sublabel,
selected: false,
checkbox: false
};
items.push(nodeItemMap[n.id]);
});
dirList.treeList('data',items);
},
oneditsave: function() {
},
oneditresize: function(size) {
this._resize();
}
});
</script>
<script type="text/html" data-template-name="Orphans">
<div class="form-row">
<label><i class="fa fa-tag"></i> <span>Orphans</span></label>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-orphan-target-filter"></div>
<div id="node-input-orphan-target-container-div"></div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name">Name</span></label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/html" data-help-name="Orphans">
<p>Orphan node shows all other nodes that are orphans, that is not connected to anything else either input nor output.</p>
</script>
module.exports = function(RED) {
function OrphanFunctionality(config) {
RED.nodes.createNode(this,config);
var node = this;
var cfg = config;
node.on('close', function() {
node.status({});
});
node.on("input",function(msg, send, done) {
send(msg);
});
}
RED.nodes.registerType("Orphans", OrphanFunctionality);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment