How to get nodes, connected to the edge is being deleted? - vis.js-network

What do I have: graph network with edges.
What do I want: I want to know, which nodes were connected to the certain edge I just deleted.
My code:
var nodes = new vis.DataSet([{
id: 1,
label: 'Node 1'
},
{
id: 2,
label: 'Node 2'
},
{
id: 3,
label: 'Node 3'
},
{
id: 4,
label: 'Node 4'
},
{
id: 5,
label: 'Node 5'
}
])
// create an array with edges
var edges = new vis.DataSet([{
from: 1,
to: 3
},
{
from: 1,
to: 2
},
{
from: 2,
to: 4
},
{
from: 2,
to: 5
},
{
from: 3,
to: 3
}
])
// create a network
var container = document.getElementById('mynetwork')
var data = {
nodes: nodes,
edges: edges
};
var options = {
interaction: {
hover: true
},
manipulation: {
enabled: true,
deleteEdge: function(edge, callback) {
callback(edge)
console.log(edge)
}
}
}
var network = new vis.Network(container, data, options)
network.on("click", function(params) {
params.event = "[original event]"
document.getElementById('eventSpan').innerHTML = '<h2>Click event:</h2>' + JSON.stringify(params, null, 4)
console.log('click event, getNodeAt returns: ' + this.getNodeAt(params.pointer.DOM))
})
<style>#mynetwork {
width: 600px;
height: 400px;
border: 1px solid lightgray;
}
</style>
<link href="https://unpkg.com/vis-network#latest/dist/vis-network.min.css" rel="stylesheet" />
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/vis-network#latest/dist/vis-network.min.js"></script>
<div id="mynetwork"></div>
<pre id="eventSpan"></pre>
Steps to reproduce:
Click "Edit"
Click on any edge, connected with two different nodes
Click "Delete selected"
Problem: edge object in console.log(edge) contains Nodes array, but it's empty. I expect it might contain array of two Nodes.

It doesn't contain nodes because no nodes were deleted. After you deleted the edge the information is lost so you have to do it before you delete it. There is network.getConnectedNodes(edgeId) method for this.

Related

Hide Pie Chart Slice on Load

I would like to hide a pie chart slice on load but cannot figure out how to do so.
I'm not sure it's possible, but it seems like it might be. There is a property "selected", but it does not seem to change when I manually select or unselect a wedge via the legend. I've tried to dispatchAction like this example (example), but haven't had any luck:
I think you are close to the solution... Actually, you should tweak legend.selected.
Take a look at this basic example:
let option = {
legend: {
selected: {
'B': false // <--- HERE
}
},
series: [
{
type: 'pie',
label: {
position: 'inner'
},
data: [
{ value: 10, name: 'A' },
{ value: 20, name: 'B' },
{ value: 15, name: 'C' }
]
}
]
};
let myChart = echarts.init(document.getElementById('main'));
myChart.setOption(option);
#main {
width: 300px;
height: 300px;
}
<script src="https://cdn.jsdelivr.net/npm/echarts#5.4.1/dist/echarts.min.js"></script>
<div id="main"></div>

Get current state of graph after elements are added dynamically

I am using Cytoscape.js and the context menus extension within a React app through react-cytoscape.js. Right now, I can dynamically add nodes through an onClickFunction as a menu item. I would like to get the current state of the graph - that is, all the nodes that have been added as well as the ones it started with.
How can I do this? So far, I've tried cy.json(), but that only returns the initial state of the graph.
Below is all of my cytoscape code.
class MyApp extends React.Component {
constructor(props){
super(props);
}
render(){
const elements = [ // Nodes and edges to be added initially
{ data: { id: 'one', label: 'Node 1' }, position: { x: 250, y: 250 } },
{ data: { id: 'two', label: 'Node 2' }, position: { x: 300, y: 250 } },
{ data: { source: 'one', target: 'two', label: 'Edge from Node1 to Node2' } }
];
return <CytoscapeComponent
cy = {cy => { // Extensions and their options
cy.contextMenus({
menuItems: [
{ // Adds the ability to add nodes from the right-click menu
id: 'add-node',
content: 'add node',
tooltipText: 'add node',
image: {src: "./node_modules/cytoscape-context-menus/assets/add.svg", width: 12, height: 12, x: 6, y: 4},
coreAsWell: true,
// When we move adding nodes to a sidebar, probably use this as reference
onClickFunction: function (event) {
var data = {
group: 'nodes'
};
var pos = event.position || event.cyPosition;
cy.add({
data: data,
position: {
x: pos.x,
y: pos.y
}
});
}
}
]
})
}}
elements={elements}
style={ { width: '100%', height: '40vmax'} } />;
}
}

How to show only first depth in cytoscape js?

Is it possible to show a root element and its neighbors only without going deeper? I need this because I want that user expands the tree by clicking on nodes, while initially, the user can see only the first level.
I'm going to use cytoscape.js-view-utilities plugin for showing/hiding elements.
I know that there is neighborhood() method, but cannot figure out how to do this
As you said, you can do it by using view-utilities extension. First you should hide all nodes except the root and its neighbors. Then with a tap event on nodes, you can show neighbors of clicked node. In the below example, if you click on node n1 and n2, their neighbors are shown. If you want to differentiate nodes with hidden neighbors, you can assign them a new class and style, and define your tap event on that class.
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
layout: {name: 'breadthfirst', directed: true},
style: [{
selector: 'node',
css: {
'label': 'data(id)'
}
}
],
elements: {
nodes: [{
data: {
id: 'n0'
}
},
{
data: {
id: 'n1'
}
},
{
data: {
id: 'n2'
}
},
{
data: {
id: 'n3'
}
},
{
data: {
id: 'n4'
}
},
{
data: {
id: 'n5'
}
},
{
data: {
id: 'n6'
}
}
],
edges: [{
data: {
id: 'n0n1',
source: 'n0',
target: 'n1',
}
},
{
data: {
id: 'n0n2',
source: 'n0',
target: 'n2'
}
},
{
data: {
id: 'n1n3',
source: 'n1',
target: 'n3'
}
},
{
data: {
id: 'n1n4',
source: 'n1',
target: 'n4'
}
},
{
data: {
id: 'n2n5',
source: 'n2',
target: 'n5'
}
},
{
data: {
id: 'n2n6',
source: 'n2',
target: 'n6'
}
}
]
}
});
var instance = cy.viewUtilities();
instance.hide(cy.elements().difference(cy.getElementById('n0').closedNeighborhood()));
cy.on('tap', 'node', function(event){
instance.show(event.target.neighborhood());
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#button {
z-index = 1000;
}
#cy {
height: 95%;
width: 95%;
left: 0;
top: 50;
z-index = 900;
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/dist/cytoscape.min.js">
</script>
<script src="https://unpkg.com/cytoscape-view-utilities/cytoscape-view-utilities.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

how to automove any node in cytoscape js

I use cytoscape js automove extention, I can move two node together:
cy.automove({
nodesMatching: cy.$('#a'),
reposition: 'drag',
dragWith: cy.$('#b')
});
But I must specify the node #a and #b, now I need whenever I move any node, its neighborhood move together, not a special node.
So I try this:
<style>
#cy{
width:600px;
height:800px
}
</style>
<script src="cytoscape.js"></script>
<script src="cytoscape-automove.js"></script>
<div id="cy"></div>
<script>
var cy = cytoscape({
container: document.getElementById('cy'), // container to render in
elements: [ // list of graph elements to start with
{ // node a
data: { id: 'a' }
},
{ // node b
data: { id: 'b' }
},
{ // node c
data: { id: 'c' }
},
{ // node d
data: { id: 'd' }
},
{ // edge ab
data: { id: 'ab', source: 'a', target: 'b' }
},
{ // edge cd
data: { id: 'cd', source: 'c', target: 'd' }
}
],
style: [ // the stylesheet for the graph
{
selector: 'node',
style: {
'background-color': '#566',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#bcc',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'grid',
rows: 1
},
boxSelectionEnabled:true,
panningEnabled: true,
selectionType:"additive"
});
cy.on("drag",function(evt){
var node=evt.target;
cy.automove({
nodesMatching: node.neighbourhood().nodes(),
reposition: 'drag',
dragWith: node
});
});
</script>
The result is once I move node #a, node #b will not move together.But I move the node #a again, #b is moved but the position is wrong, it is too far.
So does the dragWith must be a special one? What if I want to move any one?
How about this:
var i = 0;
cy.unbind("tapdrag");
cy.unbind("tapend");
cy.bind("tapdrag", "node", function(evt){
if (i = 0) {
i = 1;
var node = evt.target;
var target = cy.edges("[source = '" + node.id() + "']").target();
cy.automove({
nodesMatching: target,
reposition: 'drag',
dragWith: node
});
}
});
cy.bind("tapend", "node", function(evt) {
i = 0;
});

Vis js ionicons nodes change color when selected

I'm new in Vis.js and JavaScript but I'm willing to learn. I'm using nodes that change their color when they're hovered or selected. If I use shapes like 'dot' or 'square' it is ok, but I would like to get the same behaviour with icons like ionicons. The following code shows how I expected to get it work (using options settings). I'm planning to use selectNode and hoverNode events and updating the group (require creation of specific groups for selected or hovered nodes) but I think there is an easier way to accomplish it. Could you give me some advice? Here is my code:
// create an array with nodes
var nodes = new vis.DataSet([{
id: 1002,
label: 'Juan',
title: 'Juan Diaz Salizar',
group: 'group_1'
},
{
id: 1003,
label: 'Martin',
title: 'Sin datos',
group: 'group_2'
},
{
id: 1004,
label: 'Pedro',
title: 'Pedro Diaz Alcaraz',
group: 'group_2'
},
{
id: 1007,
label: 'Vanessa',
title: 'Juan Diaz Salizar',
group: 'group_1'
}
]);
// create an array with edges
var edges = new vis.DataSet([{
from: 1003,
to: 1002,
label: 'tc 1',
arrows: 'to'
},
{
from: 1004,
to: 1003,
label: 'tc 2',
arrows: 'to'
},
{
from: 1007,
to: 1003,
label: 'tc 2',
arrows: 'to'
},
{
from: 1007,
to: 1004,
label: 'tc',
arrows: 'to'
}
]);
// create a network
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes,
edges: edges
};
var options = {
interaction: {
hover: true
},
edges: {
font: {
size: 11,
color: 'rgb(46,117,182)'
},
color: {
color: 'rgb(189,215,238)',
hover: 'rgb(46,117,182)'
}
},
nodes: {
size: 10
},
groups: {
group_1: {
shape: 'dot',
color: {
background: 'rgb(189,215,238)',
border: 'rgb(46,117,182)',
hover: {
background: 'rgb(46,117,182)',
border: 'rgb(46,117,182)'
},
highlight: {
background: 'rgb(46,117,182)',
border: 'rgb(46,117,182)'
}
},
font: {
size: 11,
color: 'rgb(46,117,182)'
}
},
group_2: {
shape: 'icon',
icon: {
face: 'Ionicons',
code: '\uf2d2',
size: 20,
color: {
background: 'rgb(189,215,238)',
border: 'rgb(46,117,182)',
hover: {
background: 'rgb(46,117,182)',
border: 'rgb(46,117,182)'
},
highlight: {
background: 'rgb(46,117,182)',
border: 'rgb(46,117,182)'
}
}
},
font: {
size: 11,
color: 'rgb(46,117,182)'
}
}
}
};
var network = new vis.Network(container, data, options);
#mynetwork {
width: 85%;
height: 600px;
border: 1px solid lightgray;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
<div id="mynetwork"></div>
Well, as you can see from docs, for image and circularImage shapes you can set image.unselected and image.selected options, although there's no image.hover or alike. There's also chosen option of nodes but according to docs, it can't contain anything that affects node images. So I think using events that you mentioned is a proper solution, somewhat straight-forward.