Multiple data values for label text in cytoscape.js - javascript

I am trying to add multiple values to a label in cytoscape.js like so -
{
"selector": "edge",
"style": {
"curve-style": "haystack",
"text-wrap": "wrap",
"label": "data(count)" + "data(edgevalue)",
"font-size": "8px",
"color": "black",
"haystack-radius": "0.5",
"opacity": "0.4",
"line-color": "#bbb",
"width": "mapData(weight, 0, 1, 1, 8)",
}
},
However this is literally just displaying -
data(count)data(edgevalue)
As the label text. If I remove one or the other it prints the correct value for each.
I tried adding a '\n' for a line break, which created a line break but the values were just the same as above.
I also tried data(count + edgevalue) to no avail.
How can I achieve multiple data attributes in a label text?

You can use mappers to get the correct data into your styles: mappers
Also, I usually use template strings:
{
label: function (element) {
return `${element.data("attribute_01")} + ${element.data("attribute_02")}`
}
}
Here you can see a simple example:
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
// demo your layout
layout: {
name: "klay"
// some more options here...
},
style: [{
selector: "node",
style: {
"background-color": "#dd4de2"
}
},
{
selector: ".leaf",
style: {
"background-color": "#000"
}
},
{
selector: "edge",
style: {
"curve-style": "bezier",
"target-arrow-shape": "triangle",
"line-color": "#dd4de2",
"target-arrow-color": "#dd4de2",
"opacity": "0.5",
"label": function(node) {
return `${node.data("source")} -> ${node.data("target")}`
}
}
}
],
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"
}
}
],
edges: [{
data: {
source: "n0",
target: "n1"
}
},
{
data: {
source: "n1",
target: "n2"
}
},
{
data: {
source: "n1",
target: "n3"
}
},
{
data: {
source: "n2",
target: "n4"
}
},
{
data: {
source: "n4",
target: "n5"
}
},
{
data: {
source: "n4",
target: "n6"
}
},
{
data: {
source: "n6",
target: "n7"
}
},
{
data: {
source: "n6",
target: "n8"
}
},
{
data: {
source: "n8",
target: "n9"
}
},
{
data: {
source: "n8",
target: "n10"
}
},
{
data: {
source: "n10",
target: "n11"
}
},
{
data: {
source: "n11",
target: "n12"
}
},
{
data: {
source: "n12",
target: "n13"
}
},
{
data: {
source: "n13",
target: "n14"
}
},
{
data: {
source: "n13",
target: "n15"
}
}
]
}
}));
cy.nodes().leaves().addClass("leaf");
});
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;
}
<html>
<head>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/klayjs#0.4.1/klay.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-klay#3.1.3/cytoscape-klay.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Related

Set link behind background image and make it clickable Cytoscape.js

Is it possible to set a link behind the backgraound image and make it clickable for specific nodes? I am using the style and elements in seperated json files.
here is my implementation:
{
"selector": ".myImage",
"css": {
"background-image": "https://upload.wikimedia.org/wikipedia/commons/b/b4/High_above_the_Cloud_the_Sun_Stays_the_Same.jpg",
"background-width": "17px",
"background-image-opacity": 0.8,
"background-height": "15px",
"background-position-x": "50%",
"background-position-y": "0",
"padding": "5px",
"background-clip": "none",
"background-fit": "none"
}
},
}
**{
"elements": [
{
"data": {
"id": "node1",
"href": "https://js.cytoscape.org/#style"
},
"position": {
"x": 50,
"y": 300
},
"group": "nodes",
"removed": false,
"selected": false,
"selectable": false,
"locked": true,
"grabbable": true,
"classes": ""
},
]
}**
thanks for help
You can easily follow the two examples given in the docs:
Linkout Example
Images for BFS Layout
With these two, getting the link to work is really easy. I created a working example here:
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",
"border-color": "black",
"border-opacity": "1",
'background-fit': 'cover',
"border-width": "10px"
}
},
{
selector: "node[href]",
css: {
content: '',
'background-image': 'https://live.staticflickr.com/7272/7633179468_3e19e45a0c_b.jpg'
}
},
{
selector: "edge",
css: {
"target-arrow-shape": "triangle"
}
}
],
elements: {
nodes: [{
data: {
id: "n0",
href: "https://js.cytoscape.org/#collection"
}
},
{
data: {
id: "n1",
href: "https://js.cytoscape.org//#demos"
}
},
{
data: {
id: "n2",
href: "https://js.cytoscape.org/"
}
},
{
data: {
id: "n3",
href: "https://js.cytoscape.org//#notation"
}
},
{
data: {
id: "n4",
href: "https://js.cytoscape.org/"
}
},
{
data: {
id: "n5"
}
},
{
data: {
id: "n6",
href: "https://js.cytoscape.org/#core"
}
},
{
data: {
id: "n7",
href: "http://cytoscape.org"
}
},
{
data: {
id: "n8"
}
},
{
data: {
id: "n9"
}
},
{
data: {
id: "n10",
href: "https://js.cytoscape.org/#notation"
}
},
],
edges: [{
data: {
source: "n0",
target: "n1"
}
},
{
data: {
source: "n1",
target: "n2"
}
},
{
data: {
source: "n1",
target: "n3"
}
},
{
data: {
source: "n4",
target: "n5"
}
},
{
data: {
source: "n4",
target: "n6"
}
},
{
data: {
source: "n6",
target: "n7"
}
},
{
data: {
source: "n6",
target: "n8"
}
},
{
data: {
source: "n8",
target: "n9"
}
},
{
data: {
source: "n8",
target: "n10"
}
}
]
},
layout: {
name: "dagre",
padding: 5
}
}));
cy.on('tap', 'node', function() {
if (this.data('href')) {
try { // your browser may block popups
window.open(this.data('href'));
} catch (e) { // fall back on url change
window.location.href = this.data('href');
}
}
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
}
<html>
<head>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre#2.1.0/cytoscape-dagre.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
This site seems to block popups, that is why the link may not work here, but as proof, here you can see it working in my codepen. Feel free to implement this code in your project and try it out there.

Limit drop area with Cytoscape

I'm trying to make a web designer with Cytoscape, and I'd like to set a restricted area in which the user can drop a node. In essence: the user can drop a node out of the "canvas" (just a rectangle in CSS) and they get lost. Like in the image below:
As you can see, my node is shaped as a rectangle, which can be dropped out of the zone I'm trying to limit. What should I do?
Thanks!
The following code snippet uses both the built in cy.fit() function as well as the cytoscape-autopan-on-drag extension.
document.addEventListener("DOMContentLoaded", function() {
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
style: [{
selector: "node",
style: {
content: "data(id)"
}
},
{
selector: "edge",
style: {
"target-arrow-shape": "triangle"
}
},
{
selector: ":selected",
style: {}
}
],
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: "n4",
target: "n5"
}
},
{
data: {
source: "n4",
target: "n6"
}
},
{
data: {
source: "n6",
target: "n7"
}
},
{
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: 50
}
}));
// demo your core ext
cy.autopanOnDrag({
/* Options here */
});
cy.on('tapdrag', 'node', function() {
cy.fit(cy.elements(), 50);
cy.center();
})
});
body {
font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
font-size: 14px;
}
#cy {
position: absolute;
width: 60%;
height: 60%;
border: 1px solid gray;
}
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/jquery#3.4.1/dist/jquery.min.js"></script>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre#2.1.0/cytoscape-dagre.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-autopan-on-drag#2.2.0/cytoscape-autopan-on-drag.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Changing color when node is selected in Cytoscape JS

I would like to change the color of a selected node to a different color than the predefined background-color. However, as soon as I define a background color for the node in "style", the color does not change to blue (default behavior).
Here is the style I have defined:
selector: 'node',
style: {
'content': 'data(d2)',
'background-color': '#ccc',
}
Can someone help?
Lazloo
This is a fairly simple thing for cytoscape.js and I would recommend you to look at some of the examples provided in the docs.
The important part here is the :selected state, which any component has if it has been selected by a click. You can address this state in your stylesheet and add any styles you want. You can also bind this on cy.on() and add the style with cy.element(...).style().
In general, I would suggest adding a style to the cytoscape-stylesheet:
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: ':selected',
css: {
'background-color': 'SteelBlue',
'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: 100%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<html>
<head>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cytoscape-dagre#2.1.0/cytoscape-dagre.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Removing edge found in DFS algorithm cytoscape JS

Today I'm started with cytoscape and trying to make DFS search on prepared graph. I want to remove every edge that algorithm will go thought.
var dfs = cy.elements().dfs('#0', function(v, e, u, i, depth){}, false);
var highlightNextEle = function(){
if( i < dfs.path.length ){
dfs.path[i+1].remove();
i++;
setTimeout(highlightNextEle, 1000);
}
};
highlightNextEle();
I tried this code and he remove first edge but then he removes everything connected with started node.
For any tips, thank you in advance
if you want to remove the edges found in dfs, you can use the handler function inside dfs 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
}
});
cy.unbind('click');
cy.bind('click', 'node', function(evt) {
var edges = cy.collection();
var dfs = cy.elements().dfs({
roots: `#${evt.target.id()}`,
visit: function(v, e, u, i, depth) {
console.log('visit ' + v.id());
if (e) edges = edges.add(e);
},
directed: false
});
console.log(dfs);
cy.remove(edges);
});
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>
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.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>

Cytoscape Can't get click event on dynamically added elements

I am trying to get event click on recent added elements but it does not work, when I click on the older elements it works. I'm creating an edge between two nodes, and when I click on it I want it gets removed.
<!DOCTYPE>
<html>
<head>
<title>cytoscape-dagre.js demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape.min.js"></script>
<!-- for testing with local version of cytoscape.js -->
<!--<script src="../cytoscape.js/build/cytoscape.js"></script>-->
<script src="https://cdn.rawgit.com/cpettitt/dagre/v0.7.4/dist/dagre.min.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.1.2/cytoscape-dagre.js"></script>
<style>
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: relative
left: 0;
top:30;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
</style>
<script>
var connectIsClicked;
var removeIsClicked;
$(function(){
var nodeFather = "";
var nodeTarget = "";
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: false,
autounselectify: true,
layout: {
name: 'dagre'
},
style: [
{
selector: 'node',
style: {
'content': 'data(id)',
'text-opacity': 0.5,
'text-valign': 'center',
'text-halign': 'right',
'background-color': '#11479e'
}
},
{
selector: 'edge',
style: {
'width': 4,
'target-arrow-shape': 'triangle',
'line-color': '#9dbaea',
'target-arrow-color': '#9dbaea',
'curve-style': 'bezier'
}
}
],
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: 'n4', target: 'n5' } },
{ data: { source: 'n4', target: 'n6' } },
{ data: { source: 'n6', target: 'n7' } },
{ 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' } },
]
},
});
cy.nodes().on("tap", function(){
if(connectIsClicked){
if(nodeFather === ""){
nodeFather = this;
}else{
nodeTarget = this;
var edgeId = nodeFather.id()+"_"+nodeTarget.id();
var ele = cy.add([
{ group: "edges", data: {id: edgeId,source: nodeFather.id(), target: nodeTarget.id() } }
]);
nodeFather = "";
nodeTarget = "";
}
}
if(removeIsClicked){
//alert($(this));
this.remove();
}
});
cy.edges().on("tap", function(){
if(removeIsClicked){
//It does not work on dynamically edges
alert(this.id());
this.remove();
}
});
});
</script>
<script>
function connect(element){
if(!connectIsClicked){
element.style = "background-color: #ff0000;";
connectIsClicked = true;
removeIsClicked = false;
var btnRemove = document.getElementById("remove");
btnRemove.style = "";
}else{
element.style = "";
connectIsClicked = false;
}
};
function remove(element){
if(!removeIsClicked){
element.style = "background-color: #ff0000;";
removeIsClicked = true;
connectIsClicked = false;
var btnConnect = document.getElementById("connect");
btnConnect.style = "";
}else{
element.style = "";
removeIsClicked = false;
}
};
</script>
</head>
<body>
<input type="submit" id="connect" value="Connect" onclick="connect(this);">
<input type="submit" id="remove" value="Remove" onclick="remove(this);">
<h1>cytoscape-dagre demo</h1>
<div id="cy"></div>
</body>
</html>
If you make a binding on the nodes that exist at point A, how would that affect a new set of nodes that exist at a later point B?
Either listen to your newly added nodes as you add them or listen to the core with a delegate selector: http://js.cytoscape.org/#cy.on

Categories