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.
Related
I have a nested array of objects i need to change the values of a children data dynamically
[
{
type: "root",
title: "FileManager",
isDirectory: true,
children: [
{
type: "folder",
title: "animals",
isDirectory: true,
children: [
{
type: "folder",
title: "cat",
isDirectory: true,
children: [
{
type: "folder",
title: "images",
isDirectory: true,
children: [
{
type: "file",
title: "cat001.jpg",
isDirectory: false,
}, {
type: "file",
title: "cat002.jpg",
isDirectory: false,
}
]
}
]
}
]
},
{
type : "folder",
title : 'Birds',
isDirectory : true,
children : []
}
]
}
]
this is my main array of object suppose if i want to change the value of children dynamically.
lets take i want to add one more object to the children inside images array
so the path of the images array is
FileManager / animals / cat / images
how can change the value of the children in the images object dynamically?
Based on the data structure provided, you can use a recursive solution to reach the nested array you are interested in and then when the recursion hits the base case, you can either push a new object/s into the array at that specific level of depth or use a callback function to push as many new objects into it.
I am not really sure about the "dynamic" part you are referring to, but the following should place you in the right direction:
function rec(array) {
for (let i in array) {
if (array[i].children === undefined) { // BASE CASE
// console.log("base case ", array);
// push the object you want into the array, as at this point in the
// recursion you will be at the level you can modify your image array as you like
return array.push({ "myImage": "myBeautifulCatImage", "does": "poooooor"});
}
// recursive call
// visualise how deep you are going...
// console.log("rec", array[i].children);
return rec(array[i].children);
}
}
rec(arr);
// if you know log your arr as in:
// console.log("arr after recursion", rec(arr))
// you will see your new cat showing where it should be :)
If this answer helps you solving the issue, consider accepting the answer or upvoting it. Thanks.
I'm developing an web application that handles and shows large amounts of live data from some devices. To visualise the data I decided to use HighStock. It seems to work well on most of the data:
However, when the bottom navigator touches right border, the picture becomes quite different:
The timeline is almost the same, but the number of points is different, also vertical scale is different... What is this happening? How to fix it?
My code looks this way:
const ch1 = Highcharts.stockChart('chart1', {
rangeSelector: {
selected: 1,
inputEnabled: false,
buttonTheme: {visibility: 'hidden'},
labelStyle: {visibility: 'hidden'},
},
title: {
text: 'Metrics',
},
series: [{
name: 'Sensor 1', data: [],
}, {
name: 'Sensor 2', data: [],
}, {
name: 'Sensor 3', data: [],
}]
});
// a,b,c gets values from the server
// They are arrays of pairs of timestamp & value
ch1.series[0].setData(a);
ch1.series[1].setData(b);
ch1.series[2].setData(c);
// tm_min & tm_max are dynamically calculated using the data
ch1.xAxis[0].setExtremes(tm_min, tm_max);
Update: Here is an example with 2% of my data – try to do the same as shown above.
I found the solution. The issue is caused by your data and xAxis.ordinal that is enabled by default in Highstock. Your data has many empty points on the right side of the chart and because of ordinal, the empty space was not rendered, yet dataGrouping grouped data differently.
Check this here https://jsfiddle.net/BlackLabel/x1tgqbw6/ (disabled ordinal):
xAxis: {
ordinal: true
}
So, the solution is to disable xAxis.ordinal or generate your data without null points:
https://jsfiddle.net/BlackLabel/ex054oy8/
API reference:
https://api.highcharts.com/highstock/xAxis.ordinal
I have a data set that contains many fields. I have no control over the creation of this JSON. Sample:
data = [
{
'maparea':'3704000063',
'relatedsource':null,
'empcount':'198390',
'response':'78',
'mean':'61663.00',
},
...
]
The chart code is:
Highcharts.mapChart('container', {
chart: {
map: geojson
},
title: {
text: 'GeoJSON in Highmaps'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
colorAxis: {
tickPixelInterval: 100
},
series: [{
data: data,
keys: ['maparea', 'relatedsource', 'empcount', 'response', 'mean'],
joinBy: ['fips', 'maparea'],
name: 'Random data',
states: {
hover: {
color: '#a4edba'
}
},
dataLabels: {
enabled: true,
format: '{point.properties.postal}'
}
}]
});
The geoJSON uses fips to label the areas (in this case counties in NC). The map shows the state and county elements. However, no data is used to plot. This is because the HighMaps code is expecting a value element to be present in the data I think.
Is there a way to tell HighMaps what element in the data set to use to shade the choropleth?
I don't see any option to map your unique data shape to the expected keys in the data according to the docs. Per your comment this is possible with an array, but it doesn't seem to be possible with an object.
However, it's pretty simple to just remap your object to the required shape. The code below gives a partial example.
let dataMapped = data.map(obj => {
var median = Number(obj.median);
return Object.assign(obj, { name: obj.maparea, value: median });
});
And then use dataMapped as the value for your data.
There might be a more elegant way to do this in ES6 with object spread and avoid the Object.assign I am using to merge the old object with new attributes, but I don't have time to research that at the moment.
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
Given data in the form:
var grid_data = [ {Hello: 'World'}, {Jesus:'Navas'} ]
I wish to draw a grid like so:
The grid shows with 2 rows but with no data, I can't find the problem in the following code:
var grid_store = Ext.create('Ext.data.Store', {
fields: [
{name: 'Property'},
{name: 'Value'}
],
data: grid_data
});
// create the Grid
var grid_view = Ext.create('Ext.grid.Panel', {
store: grid_store,
renderTo: 'info_panel',
stateful: true,
stateId: 'stateGrid',
columns: [
{
text : 'Property',
width : 100,
sortable : true,
dataIndex: 'Property'
},
{
text : 'Value',
width : 80,
sortable : false,
dataIndex: 'Value'
}
],
height: 350,
width: 600,
title: 'Array Grid',
viewConfig: {
stripeRows: true
}
});
Renders to:
<div id="info_panel"></div>
If you're wondering how I got the example image, I changed the store to an ArrayStore and re-formatted the data into arrays, but I'd prefer to miss out that step and insert the data as-is.
edit:
I think what I'm really asking for is a way to alert extjs to use the JSON keys as values, as opposed to most of the grid examples out there that take the form:
{value: 'Hello'}, {property: 'World'}
As one of the commenters and your edit suggested, your grid is built to consume a json with 'Property' and 'Value' being the keys for the json objects. I don't know if it's possible for you to change the source of the data to send in the reformatted json, but if not, you can always just run a quick loop to do so after receiving the data:
var new_data = [];
Ext.each(grid_data, function(obj) {
for (var prop in obj) {
new_data.push({
Property: prop,
Value: obj[prop]
});
}
}, this);