I am trying to use Cystoscape (http://cytoscape.github.io/cytoscape.js/) to create a star layout. I am able to get all the nodes and relate them accordingly. What i am unable to do is to make the central node appear in the center while the others appearing in a constellation fashion.
$('#cy').cytoscape({
elements: [
{ // node n1
group: 'nodes', // 'nodes' for a node, 'edges' for an edge
data: { // element data (put dev data here)
id: 'n1', // mandatory for each element, assigned automatically on undefined
parent: 'nparent', // indicates the compound node parent id; not defined => no parent
},
position: { // the model position of the node (optional on init, mandatory after)
x: 100,
y: 100
},
selected: false, // whether the element is selected (default false)
selectable: true, // whether the selection state is mutable (default true)
locked: false, // when locked a node's position is immutable (default false)
grabbable: true, // whether the node can be grabbed and moved by the user
classes: 'foo bar' // a space separated list of class names that the element has
},
{ // node n2
group: 'nodes',
data: { id: 'n2' },
renderedPosition: { x: 200, y: 200 } // can alternatively specify position in rendered on-screen pixels
},
{ // node n3
group: 'nodes',
data: { id: 'n3', parent: 'nparent' },
position: { x: 123, y: 234 }
},
{ // node nparent
group: 'nodes',
data: { id: 'nparent' }
},
{ // edge e1
group: 'edges',
data: {
id: 'e1',
source: 'n1', // the source node id (edge comes from this node)
target: 'n2' // the target node id (edge goes to this node)
}
}
],
// so we can see the ids
style: cytoscape.stylesheet().
selector('node')
.css({
'content': 'data(id)'
})
});
Additional problem i am facing is the ability to add a new node. Being new to this library, i would appreciate any help.
Look at the link http://cytoscape.github.io/cytoscape.js/#style/properties
and change the node property "shape" to "star" as follows. It will automatically change your topology to star shape. Then you will not need to specify positions x,y of each node. And it will automatically appear in center
shape:star
Related
I'm trying to render a graph to its original state from a saved JSON object that stores the nodes and edges arrays and all of their respective data including the x,y positions. I have an onLoad function that gets triggered when the page loads:
const onLoad = (_core) => {
core.current = _core;
if (savedView.nodes && savedView.node != undefined) {
let curElements = JSON.stringify({
nodes: savedView.nodes;
edges: savedView.edges;
});
let layout = core.current._cy.layout({ name: 'preset' });
layout.run();
core.current._cy.add(JSON.parse(curElements));
In the above code snippet, _core is the core cytoscape graph object that's being passed into the function and the 'savedView' var is an object that contains the nodes and edges arrays that I want to pull out to use when re-rendering the graph. A sample of a couple of the elements contained in the nodes array:
{
classes: 'draft-entity'
data: {
id: 'rkb1'
type: 'person'
displayName: 'Bob'
elementType: 'node'
{
grabbable: true
group: "nodes"
locked: false
pannable: false
position: {x: 334.85120850976364, y: 20}
removed: false
selectable: true
selected: false
}
{
classes: 'draft-entity'
data: {
id: 'rkb2'
type: 'person'
displayName: 'Jane'
elementType: 'node'
{
grabbable: true
group: "nodes"
locked: false
pannable: false
position: {x: 237, y: 149}
removed: false
selectable: true
selected: false
}
When the nodes and edges are added to the graph, they are not rendered in the position in which they were when the graph was saved. I'm not sure what I'm doing wrong here. I've checked a couple of threads that mentioned using the 'preset' layout, but the way I'm implementing it doesn't seem to be working.
I have a stacked bar chart made with C3.js which uses the following code to be generated:
stacked_bar_chart = c3.generate({
bindto: '#stacked_bar_chart_container',
data: {
columns: [
["Critical", 446, 863],
["High", 1160, 2301],
["Medium", 3106, 8258],
["Low", 277, 119],
["Informational", 7374, 23240]
],
type: 'bar',
groups: [
['Low', 'Medium', 'Informational', 'High', 'Critical', 'Unknown']
],
},
grid: {
y: {
lines: [{ value: 0 }]
}
},
axis: {
x: {
type: 'category',
categories: ["Remediated", "Unconfirmed"] // Notice the x-axis has categories
},
y: {
label: 'Number of Findings'
}
},
});
I am trying to make it so that at the click of a button, I am able to hide the bar called Remediated from the graph. I have tried to unload it by doing the following:
stacked_bar_chart.unload("Remediated");
but this has no effect, and I am pretty sure it is because I am using type: 'category' for the x-axis. I would prefer to not have to unload the data anyways so that later on I can re-display the bar as needed without retrieving the data again.
After some research in the C3.js reference page, I think that there is no easy API function for this to be accomplished, so I have come up with my own tested implementation of this feature that I am currently using.
Firstly, with the way that I do it I am keeping track of three separate global variables which will hold the data currently in the chart and also will hold the data we remove from it. This is the way I decided to choose because the data for my chart is coming from a web resource, so it would be inefficient to keep making AJAX calls and refreshing the data every time a category is added or removed.
// Our three new variables
var removed_from_stacked_bar = {};
var stacked_bar_categories = ["Remediated", "Unconfirmed"];
var stacked_bar_data = [
["Critical", 446, 863],
["High", 1160, 2301],
["Medium", 3106, 8258],
["Low", 277, 119],
["Informational", 7374, 23240]
];
function initialize_stacked_bar_chart(data, categories) {
stacked_bar_chart = c3.generate({
bindto: '#stacked_bar_chart_container',
data: {
columns: data, // Coming from the parameter
type: 'bar',
groups: [
['Low', 'Medium', 'Informational', 'High', 'Critical', 'Unknown']
],
},
grid: {
y: {
lines: [{ value: 0 }]
}
},
axis: {
x: {
type: 'category',
categories: categories // Coming from the parameter
},
y: {
label: 'Number of Findings'
}
},
});
}
initialize_stacked_bar_chart(stacked_bar_data, stacked_bar_categories);
Now I wrote a function called update_stacked_bar_chart() which has a category parameter in order to remove / add the category that is passed in from the chart whenever it is called.
function update_stacked_bar_chart(category) {
var categoryIndex = stacked_bar_categories.indexOf(category);
var removed_values = [];
if (categoryIndex != -1) { // Removing the item since it exists in the bar chart's categories
stacked_bar_categories.splice(categoryIndex, 1); // Removing the category name from the bar chart's category list
stacked_bar_data.forEach(function (item, index) {
var temp = item.splice(categoryIndex + 1, 1); // Removing the value this category held (in-place) in the sublist for each severity
removed_values.push(temp); // Pushing each removed value into the array of removed values (in order from Critical, High, Medium, Low, Informational).
});
removed_from_stacked_bar[category] = removed_values;
} else { // Re-adding the item if it was not found in the current chart's categories
stacked_bar_categories.push(category); // Adding the category name to the bar chart's category list
removed_from_stacked_bar[category].forEach(function (item, index) {
stacked_bar_data[index].push(item); // Adding the value for each severity into the respective severity list
});
delete removed_from_stacked_bar[category];
}
initialize_stacked_bar_chart(stacked_bar_data, stacked_bar_categories); // Remaking the bar chart with the new data and categories.
}
This function will allow you to toggle any category from your bar chart every time it is called. You can attach it to an event listener so that it is called as you need it.
Here is an example of how it can be used to toggle bars as it is called:
update_stacked_bar_chart("Remediated"); // Removes the "Remediated" bar
update_stacked_bar_chart("Remediated"); // Re-adds the "Remediated" bar
update_stacked_bar_chart("Remediated"); // Removes the "Remediated" bar
update_stacked_bar_chart("Unconfirmed"); // Removes the "Unconfirmed" bar
update_stacked_bar_chart("Remediated"); // Re-adds the "Remediated" bar
update_stacked_bar_chart("Unconfirmed"); // Re-adds the "Unconfirmed" bar
I'm trying to explore the cytoscape graph core object and I want to access its properties in runtime. Can I use Node.js interpreter to instantiate the cy object and run methods on the elements ? If this is an option, I also don't understand where 're real graphics going to be displayed. Is Node.js will open a browser window ?
Node.js REPL represents JavaScript interpreter, but it has no relation to DOM. From the examples on how to use cytoscape, the DOM is required:
var cy = cytoscape({
container: document.getElementById('cy') // container to render in
});
So it seems you can't use cytoscape's visual features with REPL. However, the docs says that:
container : A HTML DOM element in which the graph should be rendered.
This is unspecified if Cytoscape.js is run headlessly.
But I think you can use REPL to run Cytoscape headlessly.
Actually i just find how to run Cytoscape in a REPL environment. still didnt find a way to display it graphically, but i can interact with the object to explore its properties :
$ node
>var cytoscape = require('cytoscape');
>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' }
},
{ // edge ab
data: { id: 'ab', source: 'a', target: 'b' }
}
],
style: [ // the stylesheet for the graph
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'grid',
rows: 1
}
});
After i instantiate the cy object, i can interact with it by typing :
> cy.
cy.__defineGetter__ cy.__defineSetter__
cy.__lookupGetter__ cy.__lookupSetter__
cy.__proto__ cy.constructor
cy.hasOwnProperty cy.isPrototypeOf
cy.propertyIsEnumerable cy.toLocaleString
cy.toString cy.valueOf
> cy.elements().forEach(function(e){ console.log(e.data())});
{ id: 'a' }
{ id: 'b' }
{ id: 'ab', source: 'a', target: 'b' }
I am using Carrot Search FoamTree code to add hyperlinks to my html page. Here is my code:
<script>
// Initialize FoamTree after the whole page loads to make sure
// the element has been laid out and has non-zero dimensions.
window.addEventListener("load", function() {
var foamtree = new CarrotSearchFoamTree({
// Identifier of the HTML element defined above
id: "visualization",
// Some data to visualize.
dataObject: { groups: [
{ label: "Alkaloid", weight: 1.0, trigger: true},
{ label: "Flavonoids", weight: 3.0 },
{ label: "Terpenoids", weight: 2.0 },
{ label: "Alkaloid", weight: 1.0 },
{ label: "Flavonoids", weight: 3.0 },
{ label: "Terpenoids", weight: 2.0 },
{ label: "Steroids", weight: 4.0 }
]},
});
});
</script>
I want to produce hyperlinks for Alkaloids, Flavonoids, Terpenoids and Steroids. How do I do that?
i have solved this problem by passing extra parameters into the dataObject, especially useful when a foamtree drills down into another foamtree. I do the same with circles, for example passing parentId and parentName into sub objects so when the onclick event fires you have all the info you need in the event object as it just passes you that object, which contains your group, so passing a url to be used in an even could simply be placed into the group object.
I am trying to use the StoreSeries with Dojo in order to create charts. However when I try to create the array by:
new StoreSeries(store, { query: { site: 1 } }, "value");
Then the javascript stops running and cannot continue to render the chart.
This is all the script that I think might be relevant - ask if you need to see any more.
function setupWeekElectricBar(Chart, theme, ClusteredColumns, Columns, Tooltip, Highlight, Observable, Memory, StoreSeries)
{
var data = [
{ id: 1, value: 5, site: 1 },
{ id: 2, value: 2, site: 1 },
{ id: 3, value: 3, site: 1 },
{ id: 4, value: 1, site: 1 },
{ id: 5, value: 3, site: 1 },
{ id: 6, value: 1, site: 1 }
];
// Create the data store
// Store information in a data store on the client side
var store = Observable(new Memory({
data: {
identifier: "id",
label: "Users Online",
items: data
}
}));
var result = new StoreSeries(store, { query: { site: 1 } }, "value");
//function does not get past here (checked using alert())
}
require([
// Require the basic chart class
"dojox/charting/Chart",
// Require the theme of our choosing
"dojox/charting/themes/Tufte",
// Charting plugins:
// We want to plot Pie and ClusteredColumns charts
"dojox/charting/plot2d/Pie",
"dojox/charting/plot2d/ClusteredColumns",
"dojox/charting/plot2d/Columns",
"dojox/charting/plot2d/Grid",
// Retrieve the Legend, Tooltip, and MoveSlice classes
"dojox/charting/action2d/Tooltip",
"dojox/charting/action2d/MoveSlice",
"dojox/charting/action2d/Highlight",
// We want to use Markers
"dojox/charting/plot2d/Markers",
// We'll use default x/y axes
"dojox/charting/axis2d/Default",
"dojo/parser",
"dojo/store/Observable",
"dojo/store/Memory",
"dojox/charting/StoreSeries",
"dijit/dijit", // loads the optimized dijit layer
"dijit/Calendar",
// Wait until the DOM is ready
"dojo/domReady!"
], function(Chart, theme, Pie, ClusteredColumns, Columns, Grid, Tooltip, MoveSlice, Highlight, Observable, Memory, StoreSeries) {
setupWeekElectricBar(Chart, theme, ClusteredColumns, Columns,Tooltip, Highlight, Observable, Memory, StoreSeries);
}
});
Fixed by moving
"dojo/store/Observable",
"dojo/store/Memory",
"dojox/charting/StoreSeries",
further up.