vis.js crossed edges in 4.21 hierarchical graph - javascript

Problem: After switchnig to new (4.21) version of vis.js (from 4.18) my graph is all messed up.
EDIT: The change occurs between versions 4.19.1 and 4.20. I guess it has something to do with multiple changes in network introduced in the 4.20 version.
I'm building a family free. I spent some time to get a nice looking graph. Then I found out that new version of vis.js is available. Once I decided to use it, the edges of my graph started to cross.
Here's my nice-looking graph using 4.18.1:
Here's what happens if I change to 4.21.0:
What did I do wrong? How to fix this? Same data, same code. The only difference is:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
instead of
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.18.1/vis.min.js"></script>
Here's the 4.18.1 fiddle and 4.21.0 fiddle.
And a full code with 4.21.0 reference below:
// create an array with nodes
var nodes = new vis.DataSet([
{id: 1, label: 'Person 1'},
{id: 2, label: 'Person 2'},
{id: 3, label: 'Person 3'},
{id: 4, label: 'Person 4'},
{id: 5, label: 'Person 5'},
{id: 6, label: 'Person 6'},
{id: 7, label: 'Person 7'},
{id: 8, label: 'Person 8'},
{id: 9, label: 'Person 9'},
{id: 10, label: 'Person 10'},
{id: 11, label: 'Person 11'},
{id: 12, label: 'Person 12'},
{id: 13, label: 'Person 13'},
{id: 14, label: 'Person 14'},
{id: 15, label: 'Person 15'},
{id: 16, label: 'Person 16'},
{id: 17, label: 'Person 17'},
{id: 18, label: 'Person 18'},
{id: 19, label: 'Person 19'},
{id: 20, label: 'Person 20'},
{id: 21, label: 'Person 21'},
{id: 22, label: 'Person 22'},
{id: 23, label: 'Person 23'},
{id: 24, label: 'Person 24'},
{id: 25, label: 'Person 25'},
{id: 26, label: 'Person 26'},
{id: 27, label: 'Person 27'},
{id: 28, label: 'Person 28'},
{id: 29, label: 'Person 29'},
{id: 30, label: 'Person 30'},
{id: 31, label: 'Person 31'},
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 5, arrows:'from'},
{from: 2, to: 23, arrows:'from'},
{from: 3, to: 2, arrows:'from'},
{from: 4, to: 2, arrows:'from'},
{from: 5, to: 7, arrows:'from'},
{from: 6, to: 9, arrows:'from'},
{from: 7, to: 13, arrows:'from'},
{from: 8, to: 11, arrows:'from'},
{from: 13, to: 16, arrows:'from'},
{from: 16, to: 14, arrows:'from'},
{from: 18, to: 25, arrows:'from'},
{from: 19, to: 26, arrows:'from'},
{from: 20, to: 30, arrows:'from'},
{from: 21, to: 28, arrows:'from'},
{from: 22, to: 20, arrows:'from'},
{from: 23, to: 18, arrows:'from'},
{from: 1, to: 6, arrows:'from'},
{from: 2, to: 22, arrows:'from'},
{from: 3, to: 1, arrows:'from'},
{from: 4, to: 1, arrows:'from'},
{from: 5, to: 8, arrows:'from'},
{from: 6, to: 10, arrows:'from'},
{from: 8, to: 12, arrows:'from'},
{from: 13, to: 17, arrows:'from'},
{from: 16, to: 15, arrows:'from'},
{from: 18, to: 24, arrows:'from'},
{from: 19, to: 27, arrows:'from'},
{from: 20, to: 31, arrows:'from'},
{from: 21, to: 29, arrows:'from'},
{from: 22, to: 21, arrows:'from'},
{from: 23, to: 19, arrows:'from'},
]);
// create a network
var container = document.getElementById('mynetwork');
// provide the data in the vis format
var data = {
nodes: nodes,
edges: edges
};
var options = {
layout: {
hierarchical: {
enabled: true,
//levelSeparation: 130,
nodeSpacing: 220,
blockShifting: false,
parentCentralization: false,
edgeMinimization: true,
direction: 'DU',
sortMethod: 'directed',
},
},
edges: {
smooth: {
type: "cubicBezier",
forceDirection: 'vertical',
roundness: 0.25
},
},
physics: false,
}
// initialize your network!
var network = new vis.Network(container, data, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
<body>
<div id="mynetwork"></div>
</body>

I usually save my graph with x,y position to avoid messup,
I believe you can try saving old graph with x,y potion that will help to open as is in new version.

Related

Having trouble accessing the nested values of my object. JavaScript

So I am trying to create a function that will list all the stats of a specific player in below object. I am simply trying to return the nested object associated with the playerName itself. I'm guessing map isn't working for me here. Instead I am returning an array of the individual letters of the name "Jeff Adrien". Can someone help me understand where I am going wrong?
//Code in question
function playerStats(playerName) {
let specificPlayer = allPlayers().players
if (playerName === specificPlayer) {
return specificPlayer
}
const stats = Object.values(playerName).map((nums) => {
return [nums]
})
return stats.flat()
}
console.log(playerStats('Jeff Adrien'))
// details
function allPlayers() {
const everyPlayer = Object.assign(homePlayers, awayPlayers)
return everyPlayer
}
const gameObject = () => {
return {
home: {
teamName: 'Brooklyn Nets',
colors: ['black', 'white'],
players: {
'Alan Anderson': {
number: 0,
shoe: 16,
points: 22,
rebounds: 12,
assists: 12,
steals: 3,
blocks: 1,
slamDunks: 1,
},
'Reggie Evans': {
number: 30,
shoe: 14,
points: 12,
rebounds: 12,
assists: 12,
steals: 12,
blocks: 12,
slamDunks: 7,
},
'Brook Lopez': {
number: 11,
shoe: 17,
points: 17,
rebounds: 19,
assists: 10,
steals: 3,
blocks: 1,
slamDunks: 15,
},
'Mason Plumlee': {
number: 1,
shoe: 19,
points: 26,
rebounds: 12,
assists: 6,
steals: 3,
blocks: 8,
slamDunks: 5,
},
'Jason Terry': {
number: 31,
shoe: 15,
points: 19,
rebounds: 2,
assists: 2,
steals: 4,
blocks: 11,
slamDunks: 1,
},
},
},
away: {
teamName: 'Charlotte Hornets',
colors: ['turquoise', 'purple'],
players: {
'Jeff Adrien': {
number: 4,
shoe: 18,
points: 10,
rebounds: 1,
assists: 1,
steals: 2,
blocks: 7,
slamDunks: 2,
},
'Bismak Biyombo': {
number: 0,
shoe: 16,
points: 12,
rebounds: 4,
assists: 7,
steals: 7,
blocks: 15,
slamDunks: 10,
},
'DeSagna Diop': {
number: 4,
shoe: 14,
points: 24,
rebounds: 12,
assists: 12,
steals: 4,
blocks: 5,
slamDunks: 5,
},
'Ben Gordon': {
number: 8,
shoe: 15,
points: 33,
rebounds: 3,
assists: 2,
steals: 1,
blocks: 1,
slamDunks: 0,
},
'Brendan Haywood': {
number: 33,
shoe: 15,
points: 6,
rebounds: 12,
assists: 12,
steals: 22,
blocks: 5,
slamDunks: 12,
},
},
},
}
}
wow I was trying to work with an array and turn it into an object somehow.. it just clicked for me
function playerStats(playerName) {
for (const player in allPlayers()) {
if (player === playerName) {
return allPlayers()[player]
}
}
}

Create unique array when merging two array

I want to merge two arrays of objects. One key will be the same in those 2 arrays.
Here is the sample data:
var a = ['Europe', 'Africa', 'Antarctica'];
var b = [
{id: 11, warehouse_name: 'Europe', input_qty: 200, total_amt: 4000},
{id: 12, warehouse_name: 'Africa', input_qty: 150, total_amt: 3500},
{id: 13, warehouse_name: 'Africa', input_qty: 20, total_amt: 500},
{id: 14, warehouse_name: 'Antarctica', input_qty: 50, total_amt: 1500}
];
My expected output should be:
var c = [
{warehouse_name: 'Europe', pack: [{id: 11, warehouse_name: 'Europe', input_qty: 200, total_amt: 4000}]},
{warehouse_name: 'Africa', pack: [{id: 12, warehouse_name: 'Africa', input_qty: 150, total_amt: 3500}, {id: 13, warehouse_name: 'Africa', input_qty: 20, total_amt: 500}]},
{warehouse: 'Antarctica', pack: [{id: 14, warehouse_name: 'Antarctica', input_qty: 50, total_amt: 1500}]}
];
How can i achieve this in javascript using lodash or without using lodash. Any solution is appreciated.
You could do it using array Array.prototype.map() method. Traverse the a array using map and filter b array by a arrays value using Array.prototype.filter method.
const a = ['Europe', 'Africa', 'Antarctica'];
const b = [
{ id: 11, warehouse_name: 'Europe', input_qty: 200, total_amt: 4000 },
{ id: 12, warehouse_name: 'Africa', input_qty: 150, total_amt: 3500 },
{ id: 13, warehouse_name: 'Africa', input_qty: 20, total_amt: 500 },
{ id: 14, warehouse_name: 'Antarctica', input_qty: 50, total_amt: 1500 },
];
const ret = a.map((x) => ({
warehouse_name: x,
pack: b.filter((y) => y.warehouse_name === x),
}));
console.log(ret);
Use _.groupBy() create an object (byWarehouse) of items by warehouse_name from array b. Now map array a, and take the items from byWarehouse to create the object:
const a = ['Europe', 'Africa', 'Antarctica'];
const b = [
{ id: 11, warehouse_name: 'Europe', input_qty: 200, total_amt: 4000 },
{ id: 12, warehouse_name: 'Africa', input_qty: 150, total_amt: 3500 },
{ id: 13, warehouse_name: 'Africa', input_qty: 20, total_amt: 500 },
{ id: 14, warehouse_name: 'Antarctica', input_qty: 50, total_amt: 1500 },
];
const byWarehouse = _.groupBy(b, 'warehouse_name')
const result = a.map(warehouse_name => ({ warehouse_name, pack: byWarehouse[warehouse_name] }))
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

how would you save and read an array of arrays in firestore?

I am trying to save react-seat-picker
https://github.com/roggervalf/react-seat-picker#readme
data into firestore and read it back.
The one piece of code describing data that should be written/saved to firestore is this:
const rows = [
[{id: 1, number: 1, isSelected: true, tooltip: 'Reserved by you'}, {id: 2, number: 2, tooltip: 'Cost: 15$'}, null, {id: 3, number: '3', isReserved: true, orientation: 'east', tooltip: 'Reserved by Rogger'}, {id: 4, number: '4', orientation: 'west'}, null, {id: 5, number: 5}, {id: 6, number: 6}],
[{id: 7, number: 1, isReserved: true, tooltip: 'Reserved by Matthias Nadler'}, {id: 8, number: 2, isReserved: true}, null, {id: 9, number: '3', isReserved: true, orientation: 'east'}, {id: 10, number: '4', orientation: 'west'}, null, {id: 11, number: 5}, {id: 12, number: 6}],
[{id: 13, number: 1}, {id: 14, number: 2}, null, {id: 15, number: 3, isReserved: true, orientation: 'east'}, {id: 16, number: '4', orientation: 'west'}, null, {id: 17, number: 5}, {id: 18, number: 6}],
[{id: 19, number: 1, tooltip: 'Cost: 25$'}, {id: 20, number: 2}, null, {id: 21, number: 3, orientation: 'east'}, {id: 22, number: '4', orientation: 'west'}, null, {id: 23, number: 5}, {id: 24, number: 6}],
[{id: 25, number: 1, isReserved: true}, {id: 26, number: 2, orientation: 'east'}, null, {id: 27, number: '3', isReserved: true}, {id: 28, number: '4', orientation: 'west'}, null,{id: 29, number: 5, tooltip: 'Cost: 11$'}, {id: 30, number: 6, isReserved: true}]
]
You can stringify your nested array (JSON.stringify(rows)) before storing in firestore and parse it after getting it back.
So far firebase firestore doesn't support nested arrays,you need to change the data structure.Have a look at this solution

With the directed sortMethod, is it possible to determine relative position of nodes in the same hierarchy?

For exemple I have a simple network:
var options = {
style = {
hierarchical = {
sortMethod = 'directed'
}
}
}
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'}
]);
var edges = new vis.DataSet([
{from: 1, to: 2},
{from: 2, to: 3},
{from: 4, to: 3},
{from: 5, to: 3}
]);
Is there a way to indicate that I want the node 2 to be rendered between node 4 and 5?
I'm afraid the only way is to set coordinates of the nodes explicitly:
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1', x: 0, y: -100},
{id: 2, label: 'Node 2', x: 0, y: 0},
{id: 3, label: 'Node 3', x: 0, y: 100},
{id: 4, label: 'Node 4', x: 100, y: 0},
{id: 5, label: 'Node 5', x: -100, y: 0}
]);
The point is, physics works only with existing nodes and edges. Still, you can try one of the following tricks:
add hidden edges between 2 and 4 and 2 and 5 – this way, you may hope that because nodes in those pairs are attracted to each other, node 2 ends up at least closer to both 4 and 5 than 4 to 5;
or instead of setting coordinates explicitly, use some pre-defined layout to put nodes in the desired order; however, as far as I know, no existing layout really garantees that this will be so (see these, these issues: this is vis.js-version-dependent and not reliable)

Is it possible to bind events to the recline.js slickgrid view using the "events" feature?

Using the SlickGrid view from recline.js, I've been trying to bind an click event to a row without success. It's easy enough to $('.slick-row').click(function() {...etc}), but I was hoping to use the backbone-esque view to handle my events. Nothing seems to fire. Context seems right. Is there something obvious I'm overlooking?
My HTML container:
<div id="mygrid" style="height: 400px"></div>
My JS:
$(function() {
var data = [
{id: 0, date: '2011-01-01', x: 1, y: 2, z: 3, country: 'DE', geo: {lat:52.56, lon:13.40} },
{id: 1, date: '2011-02-02', x: 2, y: 4, z: 24, country: 'UK', geo: {lat:54.97, lon:-1.60}},
{id: 2, date: '2011-03-03', x: 3, y: 6, z: 9, country: 'US', geo: {lat:40.00, lon:-75.5}},
{id: 3, date: '2011-04-04', x: 4, y: 8, z: 6, country: 'UK', geo: {lat:57.27, lon:-6.20}},
{id: 4, date: '2011-05-04', x: 5, y: 10, z: 15, country: 'UK', geo: {lat:51.58, lon:0}},
{id: 5, date: '2011-06-02', x: 6, y: 12, z: 18, country: 'DE', geo: {lat:51.04, lon:7.9}}
];
var dataset = new recline.Model.Dataset({
records: data
});
var $el = $('#mygrid');
var grid = new recline.View.SlickGrid({
model: dataset,
el: $el,
state: {
gridOptions: '',
},
// Click handler?
events: {
'click .slick-row': 'handleClick',
'click': 'handleClick',
},
handleClick: function(e) {
console.log('row clicked');
}
});
grid.visible = true;
grid.render();
});

Categories