Change edge label after graph was rendered - javascript

I'd like to change the label of a few specific edges after a certain event.
What would be the best way to do so?
Do I need to remove these edges, change the label tag and then add them again to cytoscape?
Best way would be something like "refresh graph".
Thanks in advance!

Here is a simple way to edit the label of any cy element:
// unbind first to prevent issues with binding conflicts
cy.unbind('click');
// change label of node to new text
cy.bind('click', 'node', function (evt) {
var target = evt.target;
target.data('label', 'new node label');
});
// change label of node to new text
cy.bind('click', 'edge', function (evt) {
var target = evt.target;
target.data('label', 'new edge label');
});
Here is a working demonstration:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
"label": "data(label)",
"text-valign": "center",
"text-halign": "center",
"height": "60px",
"width": "60px"
}
},
{
selector: "edge",
css: {
"target-arrow-shape": "triangle"
}
},
{
selector: "edge[label]",
css: {
label: "data(label)",
"text-rotation": "autorotate",
"text-margin-x": "0px",
"text-margin-y": "0px"
}
}
],
elements: {
nodes: [{
data: {
id: "Peter",
label: "Peter"
}
},
{
data: {
id: "Claire",
label: "Claire"
}
},
{
data: {
id: "Mike",
label: "Mike"
}
},
{
data: {
id: "Rosa",
label: "Rosa"
}
}
],
edges: [{
data: {
source: "Peter",
target: "Claire",
label: "edge 01"
}
},
{
data: {
source: "Claire",
target: "Mike",
label: "edge 02"
}
},
{
data: {
source: "Mike",
target: "Rosa",
label: "edge 03"
}
},
{
data: {
source: "Rosa",
target: "Peter",
label: "edge 04"
}
}
]
},
layout: {
name: "circle"
}
}));
// This is the important part
cy.unbind('click');
cy.bind('click', 'node', function(evt) {
var target = evt.target;
target.data('label', 'new node label');
});
cy.bind('click', 'edge', function(evt) {
var target = evt.target;
target.data('label', 'new edge label');
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
All you have to do now is to call the .data() function on the edges array (one by one).

Related

can parent node support other shape?

I need to define the parent node shape custom, but if I assign the shape as usual, the shape remains rectangular (instead of a star shape like in the example):
{
selector: 'node:parent',
style: {
'background-color': 'lightgrey',
'shape': 'star',
'border-color': 'cyan',
'border-radius': '50',
'background-fill': 'radial-gradient',
}
}
Desired round parent shape:
As described in this GitHub Issue, cytoscape.js does not support all node shapes for parent elements due to problems with the calculation of the parents BoundingBox.
The only supported shapes are:
rectangle
cutrectangle
roundrectangle
Here is an example for this feature:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
style: [{
selector: "node",
css: {
content: "data(id)",
"text-valign": "center",
"text-halign": "center",
height: "60px",
width: "60px"
}
},
{
selector: ':parent',
css: {
//shape: 'rectangle',
shape: 'cutrectangle',
//shape: 'roundrectangle',
}
},
{
selector: "edge",
css: {
label: "\u2B24",
"curve-style": "bezier",
"target-arrow-shape": "data(arrow)"
}
},
{
selector: ".selectedNode",
style: {
"border-width": 8,
"border-color": "#5da963"
}
}
],
elements: {
nodes: [{
data: {
id: "n0",
parent: "n4"
}
},
{
data: {
id: "n1",
parent: "n5"
}
},
{
data: {
id: "n2",
parent: "n5"
}
},
{
data: {
id: "n3",
parent: "n5"
}
},
{
data: {
id: "n4",
parent: "n5"
}
},
{
data: {
id: "n5"
}
}
],
edges: [{
data: {
source: "n0",
target: "n1",
arrow: "triangle"
}
},
{
data: {
source: "n1",
target: "n2",
arrow: "triangle"
}
},
{
data: {
source: "n1",
target: "n3",
arrow: "triangle"
}
}
]
},
layout: {
name: "concentric",
minNodeSpacing: 140
}
}));
cy.unbind("click");
cy.bind("click", "node", evt => {
cy.elements().removeClass("selectedNode");
evt.target.addClass("selectedNode");
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
left: 0;
top: 0;
float: left;
position: absolute;
}
.cxtmenu-disabled {
opacity: 0.333;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdn.jsdelivr.net/npm/cytoscape#3.10.1/dist/cytoscape.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Cytoscape, how to highlight the clicked edge?

I'm trying to get the clicked edge so to get the highlight the edge.connectedNodes().
The issue that I've found is:
even if I'm able to store the edge id using the
cy.on('tap', function (event) {
if (event.target.isEdge()) {
selectedEdgeId = event.target.id;
}
}
using
cy.edges("#" + vm.selectedEdgeId);
I get only data with length equals to 0, i.e. ca {length: 0, _private{…}}
Any suggestion on how to get the clicked edge so to get the connectedNodes()?
Event.target is the clicked edge itself, so you don't need to save the id or anything. I would suggest this approach:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
content: "data(id)",
"text-valign": "center",
"text-halign": "center",
height: "60px",
width: "100px",
shape: "rectangle",
"background-color": "data(faveColor)"
}
},
{
selector: ".highlight",
css: {
"background-color": "red"
}
},
{
selector: "edge",
css: {
"curve-style": "bezier",
"control-point-step-size": 40,
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "Top",
faveColor: "#2763c4"
}
},
{
data: {
id: "yes",
faveColor: "#37a32d"
}
},
{
data: {
id: "no",
faveColor: "#2763c4"
}
},
{
data: {
id: "Third",
faveColor: "#2763c4"
}
},
{
data: {
id: "Fourth",
faveColor: "#56a9f7"
}
}
],
edges: [{
data: {
source: "Top",
target: "yes"
}
},
{
data: {
source: "Top",
target: "no"
}
},
{
data: {
source: "no",
target: "Third"
}
},
{
data: {
source: "Third",
target: "Fourth"
}
},
{
data: {
source: "Fourth",
target: "Third"
}
}
]
},
layout: {
name: "dagre"
}
}));
// bind tapstart to edges and highlight the connected nodes
cy.bind('tapstart', 'edge', function(event) {
var connected = event.target.connectedNodes();
connected.addClass('highlight');
});
// bind tapend to edges and remove the highlight from the connected nodes
cy.bind('tapend', 'edge', function(event) {
var connected = event.target.connectedNodes();
connected.removeClass('highlight');
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
float: right;
position: absolute;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js">
</script>
<!-- cyposcape dagre -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Conditionnal styles for cytoscape.js graph

I want to change the style of my graph according to global Javascript variables. For exemple, assumung my edges got name and price attributes, I would like to make the labels of edges different, depending on a global label_type variable :
let lable_type = 'I_want_name_labels'
switch(lable_type) {
case 'I_want_name_labels':
cy.style().selector('edge').style({'label': 'data(name)'});
break;
case 'I_want_price_labels':
cy.style().selector('edge').style({'label': 'data(price)'});
break;
}
The above code does not do anything at all (no label displayed), I do not really understand why.
My edges have the following structure :
{
"data": {
"id": "node_node2",
"source": "node1",
"target": "node2",
"directed": true,
"name": "Baltazar",
"price": 1095.73
}
}
Note : I tried using cy.filter('edge').style({'label': 'data(name)'}) instead, but then data does not seems accessible this way, I got this warning :
The style property `label: data(name)` is invalid
So, how to get conditionnal styling with cytoscape.js ? What am I missing here ?
Here is the line you are looking for:
// .data() gets you all properties of the target element, .id() for example directly the id of the element
targetElement.style('label', targetElement.data('faveColor'));
Here is a working demo on how to initialize and then alter the nodes/edges label:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
"label": "data(id)",
"text-valign": "center",
"text-halign": "center",
"height": "60px",
"width": "100px",
"shape": "rectangle",
"background-color": "data(faveColor)"
}
},
{
selector: "edge",
css: {
"curve-style": "bezier",
"control-point-step-size": 40,
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "Top",
faveColor: "#2763c4",
wants: "id"
}
},
{
data: {
id: "yes",
faveColor: "#37a32d",
wants: "id"
}
},
{
data: {
id: "no",
faveColor: "#2763c4",
wants: "id"
}
},
{
data: {
id: "Third",
faveColor: "#2763c4",
wants: "color"
}
},
{
data: {
id: "Fourth",
faveColor: "#56a9f7",
wants: "color"
}
}
],
edges: [{
data: {
source: "Top",
target: "yes"
}
},
{
data: {
source: "Top",
target: "no"
}
},
{
data: {
source: "no",
target: "Third"
}
},
{
data: {
source: "Third",
target: "Fourth"
}
},
{
data: {
source: "Fourth",
target: "Third"
}
}
]
},
layout: {
name: "dagre"
}
}));
cy.bind('click', 'node, edge', function(event) {
cy.nodes().each(function(ele, i, eles) {
ele.style('label', (ele.data('wants') == 'id') ? ele.data('id') : ele.data('faveColor'));
});
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 85%;
width: 100%;
float: right;
position: absolute;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js">
</script>
<!-- cyposcape dagre -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

How to have a node's name be different than its ID using Cytoscape.js?

I'm building a web application using Cytoscape.js that visualizes protein interaction data.
Proteins (nodes) need to have ID's corresponding to strings representing their chromosome locations, because this is universal. However, I would like them to be visualized or displayed alongside their common names, and not their ID's.
Any idea how to do this? The Cytoscape documentation doesn't seem to have an answer.
You can specify the nodes name in the data field. If you want to diplay that name as the nodes label, just use the field label: "data(name)":
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
label: "data(name)", //access the nodes data with "data(...)"
// label: "data(id)",
"text-valign": "center",
"text-halign": "center",
height: "60px",
width: "100px",
shape: "rectangle",
"background-color": "data(faveColor)"
}
},
{
selector: "edge",
css: {
"curve-style": "bezier",
"control-point-step-size": 40,
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "Top",
faveColor: "#2763c4",
name: "Steve"
}
},
{
data: {
id: "yes",
faveColor: "#37a32d",
name: "Larry"
}
},
{
data: {
id: "no",
faveColor: "#2763c4",
name: "Kiwi"
}
},
{
data: {
id: "Third",
faveColor: "#2763c4",
name: "Alex"
}
},
{
data: {
id: "Fourth",
faveColor: "#56a9f7",
name: "Vader"
}
}
],
edges: [{
data: {
source: "Top",
target: "yes"
}
},
{
data: {
source: "Top",
target: "no"
}
},
{
data: {
source: "no",
target: "Third"
}
},
{
data: {
source: "Third",
target: "Fourth"
}
},
{
data: {
source: "Fourth",
target: "Third"
}
}
]
},
layout: {
name: "dagre"
}
}));
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
left: 0;
top: 0;
float: left;
position: absolute;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js">
</script>
<!-- cyposcape dagre -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
You can find this in the documents as well:
Mapping with data()
Label data field

Get nodeID in BFS cytoscape Javascript

I'm using cytoscape.js to make BFS search in custom made graph's. I need to add every node ID which has been visited in this search. I've tried something like that
document.getElementById("console").innerHTML += v.id;
in bfs function
var bfs = cy.elements().bfs('#1', function(v, e, u, i, depth){}, false);
But it's not working, I'm new in JS and programming for any advice I will be thankful.
If you want to get the id of each visited node of bfs, you can, as it is also explained right here, use the visit function like this:
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
style: [
{
selector: 'node',
css: {
'content': 'data(id)',
'text-valign': 'center',
'text-halign': 'center',
'height': '60px',
'width': '60px',
'border-color': 'black',
'border-opacity': '1',
'border-width': '10px'
}
},
{
selector: '$node > node',
css: {
'padding-top': '10px',
'padding-left': '10px',
'padding-bottom': '10px',
'padding-right': '10px',
'text-valign': 'top',
'text-halign': 'center',
'background-color': '#bbb'
}
},
{
selector: 'edge',
css: {
'target-arrow-shape': 'triangle'
}
},
{
selector: ':selected',
css: {
'background-color': 'black',
'line-color': 'black',
'target-arrow-color': 'black',
'source-arrow-color': 'black'
}
}
],
elements: {
nodes: [
{ data: { id: 'n0' } },
{ data: { id: 'n1' } },
{ data: { id: 'n2' } },
{ data: { id: 'n3' } },
{ data: { id: 'n4' } },
{ data: { id: 'n5' } },
{ data: { id: 'n6' } },
{ data: { id: 'n7' } },
{ data: { id: 'n8' } },
{ data: { id: 'n9' } },
{ data: { id: 'n10' } },
{ data: { id: 'n11' } },
{ data: { id: 'n12' } },
{ data: { id: 'n13' } },
{ data: { id: 'n14' } },
{ data: { id: 'n15' } },
{ data: { id: 'n16' } }
],
edges: [
{ data: { source: 'n0', target: 'n1' } },
{ data: { source: 'n1', target: 'n2' } },
{ data: { source: 'n1', target: 'n3' } },
{ data: { source: 'n2', target: 'n7' } },
{ data: { source: 'n2', target: 'n11' } },
{ data: { source: 'n2', target: 'n16' } },
{ data: { source: 'n3', target: 'n4' } },
{ data: { source: 'n3', target: 'n16' } },
{ data: { source: 'n4', target: 'n5' } },
{ data: { source: 'n4', target: 'n6' } },
{ data: { source: 'n6', target: 'n8' } },
{ data: { source: 'n8', target: 'n9' } },
{ data: { source: 'n8', target: 'n10' } },
{ data: { source: 'n11', target: 'n12' } },
{ data: { source: 'n12', target: 'n13' } },
{ data: { source: 'n13', target: 'n14' } },
{ data: { source: 'n13', target: 'n15' } },
]
},
layout: {
name: 'dagre',
padding: 5
}
});
// here is the important part of the code
var idList = []; // list for id storage
var bfs = cy.elements().bfs({
roots: '#n0',
visit: function (v, e, u, i, depth) {
console.log("The id of the node " + i + " is " + v.id()); // i is the number of the i'th visited node, v is the node itself
idList[i] = v.id();
},
directed: false
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Categories

Resources