sequential edge animation in cystoscape - cytoscape.js

I want to make an animation for each edge that I'm visiting sequentially, but when I try to do that the animation is done for all the edges at the same time, how can I fix this?
cy.edges().forEach(e => {
let src = parseInt(e.source().data('id'))
let trg = parseInt(e.target().data('id'))
let w = parseInt(e.style('label'))
e.animation({
'style': {'line-color': '#FF0000'}},
{'duration': '2000'}).play()
}

As you can see here, cytoscape provided this demo for your problem:
var cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
style: cytoscape.stylesheet()
.selector('node')
.style({
'content': 'data(id)'
})
.selector('edge')
.style({
'curve-style': 'bezier',
'target-arrow-shape': 'triangle',
'width': 4,
'line-color': '#ddd',
'target-arrow-color': '#ddd'
})
.selector('.highlighted')
.style({
'background-color': '#61bffc',
'line-color': '#61bffc',
'target-arrow-color': '#61bffc',
'transition-property': 'background-color, line-color, target-arrow-color',
'transition-duration': '0.5s'
}),
elements: {
nodes: [{
data: {
id: 'a'
}
},
{
data: {
id: 'b'
}
},
{
data: {
id: 'c'
}
},
{
data: {
id: 'd'
}
},
{
data: {
id: 'e'
}
}
],
edges: [{
data: {
id: 'a"e',
weight: 1,
source: 'a',
target: 'e'
}
},
{
data: {
id: 'ab',
weight: 3,
source: 'a',
target: 'b'
}
},
{
data: {
id: 'be',
weight: 4,
source: 'b',
target: 'e'
}
},
{
data: {
id: 'bc',
weight: 5,
source: 'b',
target: 'c'
}
},
{
data: {
id: 'ce',
weight: 6,
source: 'c',
target: 'e'
}
},
{
data: {
id: 'cd',
weight: 2,
source: 'c',
target: 'd'
}
},
{
data: {
id: 'de',
weight: 7,
source: 'd',
target: 'e'
}
}
]
},
layout: {
name: 'breadthfirst',
directed: true,
roots: '#a',
padding: 10
}
});
var bfs = cy.elements().bfs('#a', function() {}, true);
var i = 0;
var highlightNextEle = function() {
if (i < bfs.path.length) {
bfs.path[i].addClass('highlighted');
i++;
setTimeout(highlightNextEle, 1000);
}
};
// kick off first highlight
highlightNextEle();
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>
</head>
<body>
<div id="cy"></div>
</body>
</html>
So instead of going for the bfs path, you can define your own path and use the higlighting function of the demo.
Good luck

Related

Cytoscape edgehandles ghost preview shows "undefined" when dragging from one node to another

When using edgehandles, the cytoscape extension, to create an edge between two nodes like this, I see "undefined" at the edge of the arrow. Is there some attribute I can set to get rid of this? Either in the inputs or in the style page with a selector?
For reference, I'm using
var eh = cy.edgehandles({defaults}) and eh.enableDrawMode() with the defaults defined in the edgehandles github.
Thanks!
The code from the edge-handles demo works fine in my snippet, you can use that as a starting point:
document.addEventListener('DOMContentLoaded', function() {
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
layout: {
name: 'grid',
rows: 2,
cols: 2
},
style: [{
selector: 'node[name]',
style: {
'content': 'data(name)'
}
},
{
selector: 'edge',
style: {
'curve-style': 'bezier',
'target-arrow-shape': 'triangle'
}
},
{
selector: '.eh-handle',
style: {
'background-color': 'red',
'width': 12,
'height': 12,
'shape': 'ellipse',
'overlay-opacity': 0,
'border-width': 12, // makes the handle easier to hit
'border-opacity': 0
}
},
{
selector: '.eh-hover',
style: {
'background-color': 'red'
}
},
{
selector: '.eh-source',
style: {
'border-width': 2,
'border-color': 'red'
}
},
{
selector: '.eh-target',
style: {
'border-width': 2,
'border-color': 'red'
}
},
{
selector: '.eh-preview, .eh-ghost-edge',
style: {
'background-color': 'red',
'line-color': 'red',
'target-arrow-color': 'red',
'source-arrow-color': 'red'
}
},
{
selector: '.eh-ghost-edge.eh-preview-active',
style: {
'opacity': 0
}
}
],
elements: {
nodes: [{
data: {
id: 'j',
name: 'Jerry'
}
},
{
data: {
id: 'e',
name: 'Elaine'
}
},
{
data: {
id: 'k',
name: 'Kramer'
}
},
{
data: {
id: 'g',
name: 'George'
}
}
],
edges: [{
data: {
source: 'j',
target: 'e'
}
},
{
data: {
source: 'j',
target: 'k'
}
},
{
data: {
source: 'j',
target: 'g'
}
},
{
data: {
source: 'e',
target: 'j'
}
},
{
data: {
source: 'e',
target: 'k'
}
},
{
data: {
source: 'k',
target: 'j'
}
},
{
data: {
source: 'k',
target: 'e'
}
},
{
data: {
source: 'k',
target: 'g'
}
},
{
data: {
source: 'g',
target: 'j'
}
}
]
}
});
var eh = cy.edgehandles();
document.querySelector('#draw-on').addEventListener('click', function() {
eh.enableDrawMode();
});
document.querySelector('#draw-off').addEventListener('click', function() {
eh.disableDrawMode();
});
document.querySelector('#start').addEventListener('click', function() {
eh.start(cy.$('node:selected'));
});
});
body {
font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
font-size: 14px;
}
#cy {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
font-weight: bold;
}
#buttons {
position: absolute;
right: 0;
bottom: 0;
z-index: 99999;
}
<html>
<head>
<title>cytoscape-edgehandles.js demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-edgehandles#3.6.0/cytoscape-edgehandles.min.js"></script>
</head>
<body>
<h1>cytoscape-edgehandles demo</h1>
<div id="cy"></div>
<div id="buttons">
<button id="start">Start on selected</button>
<button id="draw-on">Draw mode on</button>
<button id="draw-off">Draw mode off</button>
</div>
</body>
</html>

Cytoscape js - Call a function whenever a node is clicked

I initialized the cytoscape like this:
var cy = cytoscape({
container: document.getElementById('cy'),
elements: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'c' } },
{
data: {
id: 'ab',
source: 'a',
target: 'b'
}
},
{
data: {
id: 'ac',
source: 'a',
target: 'c'
}
}
]
});
Then I added a function which adds a new node whenever the user double clicks on the viewport.
var nid = 1;
document.getElementById("cy").ondblclick = function(e) {
cy.add({ data: { id: nid }, renderedPosition: { x: e.x, y: e.y } });
nid++;
};
Then I wrote this function which should be called whenever user clicks a node. It works whenever user clicks on a node which I added manually when initializing the cytoscape but the problem is its not working for the nodes which user added by double clicking.
cy.$('node').on('click', function (e) {
console.log('node clicked: ', e.target.id());
});
Any idea what am I doing wrong?
I have a working version of your code here:
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",
"background-color": "data(faveColor)"
}
},
{
selector: "edge",
css: {
"curve-style": "bezier",
"control-point-step-size": 40,
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "a",
faveColor: "#2763c4"
}
},
{
data: {
id: "b",
faveColor: "#37a32d"
}
},
{
data: {
id: "c",
faveColor: "#37a32d"
}
}
],
edges: [{
data: {
source: "a",
target: "b"
}
},
{
data: {
source: "a",
target: "c"
}
}
]
},
layout: {
name: "dagre"
}
}));
cy.ready(function() {
cy.dblclick();
});
var nid = 0;
cy.bind('dblclick', function(evt) {
cy.add({
group: 'nodes',
data: {
id: nid,
faveColor: 'red'
},
position: {
x: evt.x,
y: evt.y
}
});
nid++;
});
cy.bind('click', 'node', function(evt) {
console.log('node clicked: ', evt.target.id());
});
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>
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
I used the cy.on()/cy.bind() method, that seems to work with newly added nodes :)

How do you create taxi edges between parent nodes?

I'm trying to create an edge between two parent nodes using 'curve-style': 'taxi'. Unfortunately, edges between parent nodes don't seem to turn at right angles and generally route themselves very erratically.
window.addEventListener('DOMContentLoaded', function() { // on dom ready
// photos from flickr with creative commons license
var cy = cytoscape({
container: document.getElementById('cy'),
style: cytoscape.stylesheet()
.selector('node')
.style({
'height': 80,
'width': 80,
'background-fit': 'cover',
'border-color': '#000',
'border-width': 3,
'border-opacity': 0.5
})
.selector('.eating')
.style({
'border-color': 'red'
})
.selector('.eater')
.style({
'border-width': 9
})
.selector('edge')
.style({
'width': 6,
'target-arrow-shape': 'triangle',
'line-color': '#ffaaaa',
'target-arrow-color': '#ffaaaa',
'curve-style': 'taxi'
})
.selector('#bird')
.style({
'background-image': 'https://farm8.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg'
})
.selector('#cat')
.style({
'background-image': 'https://farm2.staticflickr.com/1261/1413379559_412a540d29_b.jpg'
})
.selector('#ladybug')
.style({
'background-image': 'https://farm4.staticflickr.com/3063/2751740612_af11fb090b_b.jpg'
})
.selector('#aphid')
.style({
'background-image': 'https://farm9.staticflickr.com/8316/8003798443_32d01257c8_b.jpg'
})
.selector('#rose')
.style({
'background-image': 'https://farm6.staticflickr.com/5109/5817854163_eaccd688f5_b.jpg'
})
.selector('#grasshopper')
.style({
'background-image': 'https://farm7.staticflickr.com/6098/6224655456_f4c3c98589_b.jpg'
})
.selector('#plant')
.style({
'background-image': 'https://farm1.staticflickr.com/231/524893064_f49a4d1d10_z.jpg'
})
.selector('#wheat')
.style({
'background-image': 'https://farm3.staticflickr.com/2660/3715569167_7e978e8319_b.jpg'
}),
elements: {
nodes: [{
data: {
id: 'cat',
parent: 'bird'
}
},
{
data: {
id: 'bird'
}
},
{
data: {
id: 'ladybug'
}
},
{
data: {
id: 'aphid'
}
},
{
data: {
id: 'rose'
}
},
{
data: {
id: 'grasshopper'
}
},
{
data: {
id: 'plant'
}
},
{
data: {
id: 'wheat'
}
}
],
edges: [{
data: {
source: 'cat',
target: 'bird'
}
},
{
data: {
source: 'bird',
target: 'ladybug'
}
},
{
data: {
source: 'bird',
target: 'grasshopper'
}
},
{
data: {
source: 'grasshopper',
target: 'plant'
}
},
{
data: {
source: 'grasshopper',
target: 'wheat'
}
},
{
data: {
source: 'ladybug',
target: 'aphid'
}
},
{
data: {
source: 'aphid',
target: 'rose'
}
}
]
},
layout: {
name: 'breadthfirst',
directed: true
}
}); // cy init
}); // on dom ready
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
<!DOCTYPE html>
<html>
<head>
<link href="style.css" rel="stylesheet" />
<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">
<title>Images</title>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
Is there a way to get taxi edges to behave the same way they do between non-parent nodes?
This is caused by a weired layout behaviour in the breadthfirst layout. When using compound nodes in breadthfirst, it seems that the layout can't handle inner nodes that well, so the outer edges are not really bfs edges (bonding together), but rather two seperate bfs edges (not bonding). In order to get the 'curve-style': 'taxi' to work, there is one simple but dumb way I think. Unfortunately, edges between parent nodes can't seem to turn at the right angles, so we have to make the bfs layout without the child nodes and add them afterwards (this is a stupid hack, but it works if you save all child nodes and add them afterwards:
window.addEventListener('DOMContentLoaded', function() { // on dom ready
// photos from flickr with creative commons license
var cy = cytoscape({
container: document.getElementById('cy'),
style: cytoscape.stylesheet()
.selector('node')
.style({
'height': 80,
'width': 80,
'background-fit': 'cover',
'border-color': '#000',
'border-width': 3,
'border-opacity': 0.5
})
.selector('.eating')
.style({
'border-color': 'red'
})
.selector('.eater')
.style({
'border-width': 9
})
.selector('edge')
.style({
"curve-style": "taxi",
"taxi-direction": "downward",
"taxi-turn": 20,
"taxi-turn-min-distance": 5
})
.selector('#bird')
.style({
'background-image': 'https://farm8.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg'
})
.selector('#cat')
.style({
'background-image': 'https://farm2.staticflickr.com/1261/1413379559_412a540d29_b.jpg'
})
.selector('#ladybug')
.style({
'background-image': 'https://farm4.staticflickr.com/3063/2751740612_af11fb090b_b.jpg'
})
.selector('#aphid')
.style({
'background-image': 'https://farm9.staticflickr.com/8316/8003798443_32d01257c8_b.jpg'
})
.selector('#rose')
.style({
'background-image': 'https://farm6.staticflickr.com/5109/5817854163_eaccd688f5_b.jpg'
})
.selector('#grasshopper')
.style({
'background-image': 'https://farm7.staticflickr.com/6098/6224655456_f4c3c98589_b.jpg'
})
.selector('#plant')
.style({
'background-image': 'https://farm1.staticflickr.com/231/524893064_f49a4d1d10_z.jpg'
})
.selector('#wheat')
.style({
'background-image': 'https://farm3.staticflickr.com/2660/3715569167_7e978e8319_b.jpg'
}),
elements: {
nodes: [{
data: {
id: 'bird'
}
},
{
data: {
id: 'ladybug'
}
},
{
data: {
id: 'aphid'
}
},
{
data: {
id: 'rose'
}
},
{
data: {
id: 'grasshopper'
}
},
{
data: {
id: 'plant'
}
},
{
data: {
id: 'wheat'
}
}
],
edges: [{
data: {
source: 'bird',
target: 'ladybug'
}
},
{
data: {
source: 'bird',
target: 'grasshopper'
}
},
{
data: {
source: 'grasshopper',
target: 'plant'
}
},
{
data: {
source: 'grasshopper',
target: 'wheat'
}
},
{
data: {
source: 'ladybug',
target: 'aphid'
}
},
{
data: {
source: 'aphid',
target: 'rose'
}
}
]
},
layout: {
name: 'breadthfirst',
directed: true
}
}); // cy init
cy.ready(function() {
cy.ready(function() {
cy.add({
data: {
id: 'cat',
parent: 'bird'
}
});
});
});
}); // on dom ready
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
<!DOCTYPE html>
<html>
<head>
<link href="style.css" rel="stylesheet" />
<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">
<title>Images</title>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
I added a couple of lines in the css section of cytoscape, also the cy.ready() part at the end of the js file.
I dug into the source code a bit and found that you can make this work as expected by setting the target-endpoint and source-endpoint edge style attributes to outside-to-node.
There's a bit of a funky behavior where the edge disappears when the parent nodes get too close. I found that setting 'edge-distances': 'node-position' and 'taxi-turn-min-distance': '0px' helped with that. Here is the full edge style for reference:
'curve-style': 'taxi',
'edge-distances': 'node-position',
'taxi-turn-min-distance': '0px',
'source-arrow-shape': 'triangle-backcurve',
'target-arrow-shape': 'triangle',
'target-endpoint': 'outside-to-node',
'source-endpoint': 'outside-to-node'

Content and Label on a Node - Cytoscape

I'm trying to display nodes that have a font icon in the center of the node using 'content' and a text label underneath.
My styling is currently:
{
'selector': 'node[icon]',
'style': {
'content': 'data(icon)',
'font-family': 'Material Icons',
'text-valign': 'center',
'text-halign': 'center'
}
},
{
'selector': 'node[label]',
'style': {
'label': 'data(label)',
'text-valign': 'bottom',
'text-halign': 'center'
}
}
However, this doesn't work as i assume both of the styles is used on one element (the node).
There are a few solutions I've considered, such as:
Putting the label on a parent node
Use Popper.js or similar to show the label
Use a multi-lined label
The first 2 seem 'hacky', and the third could cause a lot of alignment problems. Is there a better solution to this?
I've found a solution using the extension: https://github.com/kaluginserg/cytoscape-node-html-label.
You can create custom HTML labels for nodes which do not interfere with the base Cytoscape labels. An example of using the Material Icons:
// Initialise the HTML Label
this.cy.nodeHtmlLabel([{
query: '.nodeIcon',
halign: 'center',
valign: 'center',
halignBox: 'center',
valignBox: 'center',
tpl: (data) => {
return '<i class="material-icons">' + data.icon + '</i>';
}
}]);
// Add the HTML Label to the node:
const node = {
group: 'nodes',
data: {
id: data.id,
label: data.label,
icon: data.icon
},
classes: 'nodeIcon' // <---- Add the HTML Label class here
};
With the method you can dynamically create nodes with font icons without the need to download a load of images.
You can even add CSS styling to change the colour of the icon:
If you want an icon as the nodes body, you can use it as the background image and define the label like you do:
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: 'node',
css: {
'label': 'data(id)',
'text-valign': 'bottom',
'text-halign': 'center',
'height': '60px',
'width': '60px',
'border-color': 'black',
'border-opacity': '1',
'background-image': 'https://farm8.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg',
"text-background-opacity": 1,
"text-background-color": "lightgray"
}
},
{
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
}
});
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>

Is there a way to show connections from compound nodes to the children in Cytoscape.js

I am exploring the potential of Cytoscape.js, and would like to know if it is possible to visualize connections from compound nodes (parents) to children within this node.
In the example below I would like to show the connection between the parent node 'b' and the children 'a' and 'c', but so far I am unsuccessful.
Minimal working example is given below below, and editable here: http://jsbin.com/lelinaduko/3/edit
elements: {
nodes: [
{ data: { id: 'a', parent: 'b' } },
{ data: { id: 'c', parent: 'b' } },
{ data: { id: 'd' } },
{ data: { id: 'e' } },
{ data: { id: 'f', parent: 'e' } },
{ data: { id: 'b' } }
],
edges: [
{ data: { id: 'bd', source: 'b', target: 'd' } },
{ data: { id: 'eb', source: 'e', target: 'b' } },
{ data: { id: 'ca', source: 'c', target: 'a' } },
{ data: { id: 'ab', source: 'a', target: 'b' } },
{ data: { id: 'bc', source: 'b', target: 'c' } }
]
},
<!DOCTYPE html>
<!--
Created using JS Bin
http://jsbin.com
Copyright (c) 2015 by anonymous (http://jsbin.com/lelinaduko/3/edit)
Released under the MIT license: http://jsbin.mit-license.org
-->
<meta name="robots" content="noindex">
<html>
<head>
<link href="style.css" rel="stylesheet" />
<meta charset=utf-8 />
<title>Cytoscape.js initialisation</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape.min.js"></script>
<script src="code.js"></script>
<style id="jsbin-css">
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
#info {
color: #c88;
font-size: 1em;
position: absolute;
z-index: -1;
left: 1em;
top: 1em;
}
</style>
</head>
<body>
<div id="cy"></div>
<script id="jsbin-javascript">
$(function(){ // on dom ready
var cy = cytoscape({
container: $('#cy')[0],
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(id)',
'text-valign': 'center',
'text-halign': 'center',
'color': 'black'
})
.selector('$node > node')
.css({
'content': 'data(id)',
'text-valign': 'top',
'text-halign': 'center',
'color': 'blue'
})
.selector('edge')
.css({
'target-arrow-shape': 'triangle',
'target-arrow-color': 'black',
'source-arrow-color': 'black',
'line-color': 'red',
'line-style': 'dashed',
'text-valign': 'top',
'text-halign': 'center',
'content': 'data(id)'
})
.selector(':selected')
.css({
'background-color': '',
'line-color': 'black',
'target-arrow-color': 'black',
'source-arrow-color': 'black'
}),
elements: {
nodes: [
{ data: { id: 'a', parent: 'b' } },
{ data: { id: 'c', parent: 'b' } },
{ data: { id: 'd' } },
{ data: { id: 'e' } },
{ data: { id: 'f', parent: 'e' } },
{ data: { id: 'b' } }
],
edges: [
{ data: { id: 'bd', source: 'b', target: 'd' } },
{ data: { id: 'eb', source: 'e', target: 'b' } },
{ data: { id: 'ca', source: 'c', target: 'a' } },
{ data: { id: 'ab', source: 'a', target: 'b' } },
{ data: { id: 'bc', source: 'b', target: 'c' } }
]
},
layout: {
name: 'breadthfirst',
directed: false,
avoidOverlap: true,
padding: 5
}
});
}); // on dom ready
</script>
</body>
</html>
It seems you found a bug:
https://github.com/cytoscape/cytoscape.js/issues/866
Use haystack edges instead if you want to work around the issue until a new release -- as those edges are unaffected.