Vis.js Timeline embedded in application causing errors - javascript

I just try to recreate this grouping example: https://jsfiddle.net/api/post/library/pure/
var now = moment().minutes(0).seconds(0).milliseconds(0);
var itemCount = 60;
// create a data set with groups
var groups = new vis.DataSet();
groups.add([
{
id: 1,
content: "Lee",
nestedGroups: [11, 12, 13],
},
{
id: 2,
content: "invisible group",
visible: false,
},
{
id: 3,
content: "John",
nestedGroups: [14],
showNested: false,
},
{
id: 4,
content: "Alson",
},
]);
groups.add([
{
id: 11,
content: "cook",
},
{
id: 12,
content: "shop",
},
{
id: 13,
content: "clean house",
},
{
id: 14,
content: "wash dishes",
},
]);
// create a dataset with items
var items = new vis.DataSet();
var groupIds = groups.getIds();
var types = ["box", "point", "range", "background"];
for (var i = 0; i < itemCount; i++) {
var start = now.clone().add(Math.random() * 200, "hours");
var end = start.clone().add(2, "hours");
var randomGroupId = groupIds[Math.floor(Math.random() * groupIds.length)];
var type = types[Math.floor(4 * Math.random())];
items.add({
id: i,
group: randomGroupId,
content: "item " + i,
start: start,
end: end,
type: type,
});
}
// create visualization
var container = document.getElementById("visualization");
var options = {
groupOrder: "content", // groupOrder can be a property name or a sorting function
};
var timeline = new vis.Timeline(container, items, groups, options);
However I embed it in my own application which has, among others a menu structure (using toggle an collapse).
My Vis time works for the best part without any problems but toggling the groups gives strange behavior. Groups are disappearing and sub groups are not shown.
I assume this is caused by event-triggering confusion.
Is there a way I can isolate the vis.js events from my hosting application?
Never experienced something like this before so no clue how to solve it.

Related

how to calculate the missing quantity and items in javascript?

I have a product which is made of many x materials, each material can be made of other materials or be pure. If they are made of other materials, it is specified which materials are need with their needed quantity and currently available quantity for the item. I want to calculate how many material I have and I don't have, and for the material I don't have, I want to sum all the missing quantities.
Right know I am getting right the material quantity in the "first level" when the product is missing a material which is not used in submaterials. When I try to sum the missing submaterials the operation is not right.
How can I calculate the materials needed to create a product and each materials?
Here is the code I write:
const product = {
name: 'prod_1',
quantity: 1.2,
material_quantities: [
{ id: 2, quantity: 2 },
{ id: 1, quantity: 2 },
],
};
const materials = [
{
id: 1,
name: 'material1',
quantity: 1.2,
material_quantities: null,
},
{
id: 2,
name: 'material2',
quantity: 1.2,
material_quantities: [{ id: 1, quantity: 2 }],
},
];
function areEnoughMaterials(materialId, neededQuantity) {
const mainMaterial = materials.find(id === materialId);
const inStock = parseFloat(neededQuantity) <= parseFloat(mainMaterial.quantity);
if (mainMaterial?.material_list?.length === 0 && inStock) {
materialsStatus.available[materialId] = mainMaterial.quantity;
}
if (!inStock) {
if (!materialsStatus.missing[materialId]) {
materialsStatus.missing[materialId] =
parseFloat(neededQuantity) - parseFloat(mainMaterial.quantity);
} else {
materialsStatus.missing[materialId] =
materialsStatus.missing[materialId] + parseFloat(mainMaterial.quantity);
}
}
if (mainMaterial.material_quantities) {
for (const material of mainMaterial.material_quantities) {
areEnoughMaterials(material.id, material.quantity);
}
}
return;
}
let materialsStatus = {
available: {},
missing: {},
};
for (const material of product.material_quantities) {
areEnoughMaterials(material.id, material.quantity);
}
The output I am expecting is this:
{
available: { 2:1.2, 1:1.2 },
missing:{ 2:0.8, 1:3.6 }
}

Combine two one dimensional arrays to create a cartesian table

I hope you are good.
I am struggling to create a compatible data type in javascript to display a cartesian like table where we have a vertical and a horizontal header.
Basically I have 3 one dimensional arrays where the first two are the table headers, and the third has the combination of those two by id's (basically the table cells).
let horizontal_header = [
{ id: 1, name: 'h1' },
{ id: 2, name: 'h2' },
];
let vertical_header = [
{ id: 10, name: 'r1' },
{ id: 11, name: 'r2' },
];
let cells = [
{ hid: 1, vid: 10, id: 7, name: 'c1' },
{ hid: 1, vid: 11, id: 8, name: 'c2' },
{ hid: 2, vid: 10, id: 9, name: 'c3' },
{ hid: 2, vid: 11, id: 10, name: 'c4' },
],
Also it can happen that a combination might not exists in that case, I want to enter an empty cell or something obvious that this cell is missing.
I want to create a table like below:
h1
h2
r1
c1
c3
r2
c2
c4
I would appreciate any suggestion and be very thankful to help me solve this complex use-case using Angular for rendering the table template.
Thank you.
I'd approach this problem by parsing the cells into more table-render friendly format like below. Note: I used ### separator, you can use anything that suits for coding practice.
let output = {};
cells.forEach(cell => {
output[cell.hid + '###' + cell.vid] = {
id: cell.id,
name: cell.name,
};
});
After that, you can use the output object to render the table cell as you already know the combination of hid and vid. You can prepare/render your table rows as below.
const rows = [];
for (let i = 0; i < horizontal_header.length; i++) {
const row = [];
for (let j = 0; j < vertical_header.length; j++) {
const hid = horizontal_header[i];
const vid = vertical_header[j];
if (output[hid + '###' + vid]) {
row.push(output[hid + '###' + vid].name);
} else {
row.push('-');
}
}
rows.push(row);
}

How to select all child nodes on selecting parent in kendo TreeList? javascript

I'm trying to select child nodes on parent node clicked. I couldn't find any example for select api. Should i use checkbox instead?
<button id="btn">Highlight third row</button>
<div id="treeList"></div>
<script>
$("#treeList").kendoTreeList({
columns: [
{ field: "id" },
{ field: "name" },
{ field: "age" }
],
dataSource: [
{ id: 1, parentId: null, name: "Jane Doe", age: 22, expanded: true },
{ id: 2, parentId: 1, name: "John Doe", age: 24 },
{ id: 3, parentId: 1, name: "Jenny Doe", age: 3 }
],
selectable: "multiple row"
});
</script>
I am trying to do that if select "1" (top parent), select 2,3 (child nodes). Hope there is native solution for javascript implementation. Thanks in advice!
The selection state is maintained by TreeList in the data items row rendering<tr k-state-selected>, and that state is not reflected in the TreeList dataSource. Also, the data source is the only place the child relationship is discoverable. So there is a bit of back and forth to deal with selections and children.
Also TreeList does not have a select event like TreeView so out of the box you do not know which nodes were selected or deselected.
The change event fires when one action causes one or more rows (like shift-click can do) are caused to be selected or deselected. Within your change handler you can only know the current state of all selected rows using the select() method.
Thus, within change, you need to track prior selection state and current selection state to find which rows changed selection state, which would merit their children to be selected or deselected according to your requirement.
See this Dojo for an example. It's not perfect because in the change event you can only determine selected nodes and not know if a 'reselection' occurred (i.e. clicked on a selected row again). Anyway, the descent down the hierarchy of the TreeList is performed recursively and relies on the dataSource data item property .hasChildren and dataSource method .childNodes()
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TreeList select (change)</title>
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.219/styles/kendo.common.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.219/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.219/styles/kendo.default.min.css">
<link rel="stylesheet" href="https://kendo.cdn.telerik.com/2020.1.219/styles/kendo.mobile.all.min.css">
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.219/js/angular.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.219/js/jszip.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2020.1.219/js/kendo.all.min.js"></script></head>
<body>
<p><a target="_blank" href="https://docs.telerik.com/kendo-ui/api/javascript/ui/treelist">TreeList docs</a></p>
<div id="treeList"></div>
<script>
selected_uids = []; // track selected uids
autoselecting = false;
$("#treeList").kendoTreeList({
columns: [
{ field: "id" },
{ field: "name" },
{ field: "age" }
],
dataSource: [
{ id: 1, parentId: null, name: "Jane Doe", age: 22, expanded: false },
{ id: 2, parentId: 1, name: "John Doe", age: 24 },
{ id: 3, parentId: 1, name: "Jenny Doe", age: 3 },
{ id: 4, parentId: null, name: "Jane Mack", age: 22, expanded: false },
{ id: 5, parentId: 4, name: "John Mack", age: 24 },
{ id: 6, parentId: 4, name: "Jenny Mack", age: 3 }
],
selectable: "multiple row",
change: function(e) {
if (autoselecting) {
e.preventDefault();
return;
}
debugger;
autoselecting = true;
var selected_rows = this.select();
console.log ('desel',selected_rows, selected_uids);
// check for new deselections
for (var index = 0; index < selected_uids.length; index++) {
var selected_uid = selected_uids[index];
if (selected_uid) {
var row = $("tr[data-uid='" + selected_uid + "'].k-state-selected");
if (row.length == 0) {
// no such selected row for one that was previously tracked as selected
deselectChildren(this, selected_uid);
selected_uids[index] = null; // untrack
}
}
}
var selected_rows = this.select();
console.log ('sel',selected_rows,selected_uids);
// check for new selections
for (var index = 0; index < selected_rows.length; index++) {
var data = this.dataItem(selected_rows[index]);
console.log('data',data);
if (jQuery.inArray(data.uid, selected_uids) == -1) {
// new selection
selected_uids.push(data.uid);
selectChildren(this, data);
}
}
for (var i=0, j=0; i < selected_uids.length; i++) {
if (selected_uids[i] != null) {
if (i > j) {
selected_uids[j] = selected_uids[i];
}
j++;
}
}
selected_uids.length = j;
autoselecting = false;
},
});
function selectChildren(treeList, data) {
if (!data.hasChildren) return;
var children = treeList.dataSource.childNodes(data);
for (var index = 0; index < children.length; index++) {
var child = children[index];
if (jQuery.inArray(child.uid, selected_uids) == -1) {
selected_uids.push(child.uid);
treeList.select($("tr[data-uid='" + child.uid + "']"));
selectChildren(treeList,child);
}
}
}
function deselectChildren(treeList, uid) {
var data = treeList.dataSource.getByUid(uid);
if (!(data && data.hasChildren)) return;
var children = treeList.dataSource.childNodes(data);
for (var index = 0; index < children.length; index++) {
var child = children[index];
var row = $("tr[data-uid='" + child.uid + "'].k-state-selected");
if (row.length == 1) {
var at = selected_uids.indexOf(child.uid);
if (at >= 0) selected_uids[at] = null;
row.removeClass('k-state-selected');
}
deselectChildren(treeList,child.uid);
}
}
$("#treeList").data("kendoTreeList").select($("#treeList tbody>tr:nth(0)"));
</script>
</body>
</html>

How to avoid Edge overlap when having two self loops Edges for the same Node

I have this issue when using the Vis.js library.
I am trying to create one node with two self-loop edges.
The issue is that the edges overlap and the labels are not readable.
I have tried changing some physics parameters but had no luck with it.
Here is what I would like to achieve:
// create an array with nodes
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 1, label: "0"},
{from: 1, to: 1, label: "1"}
]);
// create a network
var container = document.getElementById('mynetwork');
// provide the data in the vis format
var data = {
nodes: nodes,
edges: edges
};
var options = {physics:{enabled:true}};
// initialize your network!
var network = new vis.Network(container, data, options);
As you can see from the image result, the labels overlap:
https://ibb.co/gmT8v8q
Do you have any solutions for this problem ?
Thanks in advance,
Andrea
Try the angle parameter in selfReferences property of Edges. It will create multiple self edges at different angle of the node circle.
var data = {
nodes:
[
{id:1, label: "Entity 1", shape: 'circle'},
],
edges:
[
{"from":1,"to":1,"arrows":"to","label":"Prg",
selfReference:{
size: 20,
angle: Math.PI / 4,
renderBehindTheNode: true
}
},
{"from":1,"to":1,"arrows":"to","label":"Boot", selfReference:{
size: 20,
angle: Math.PI / 1,
renderBehindTheNode: true
} },
]};
Velu's solution works great. Just wanted to add that changing the top-level selfReferenceSize param should also do the trick:
// create a network
var container = document.getElementById('mynetwork');
// provide the data in the vis format
var data = {
nodes:
[
{id:1, label: "Entity 1", shape: 'circle'},
],
edges:
[
{
"from":1,"to":1,"arrows":"to","label":"Edge 1",
selfReferenceSize: 50
},
{
"from": 1, "to": 1, "arrows": "to", "label": "Edge 2",
selfReferenceSize: 20
}
]
};
var options = {physics:{enabled:true}};
// initialize your network!
var network = new vis.Network(container, data, options);

Access data from an array with jquery

Im trying to loop through an array only i cant seem to extract the data from my array...
http://jsfiddle.net/338Ud/
var listTicker = function (options) {
var defaults = {
list: [],
startIndex: 0,
interval: 3 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function (index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value = options.list[index];
options.trickerPanel.fadeOut(function () {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function () {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
}
var textlist = new Array({
id: 0,
name: 'Antonia Lallement',
title: '\u003cp\u003e\u003cspan\u003eConsultant\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI started as a resourcer at company three months ago so I\u0026rsquo;m a new team member. Sin...',
image: 'antonia.jpg'
}, {
id: 1,
name: 'Camilla Gobel',
title: '\u003cp\u003e\u003cspan\u003eBusiness Manager\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI joined company in 2011. As a multilingual Consultant, my initial focus was the provisi...',
image: 'camilla.jpg'
}, {
id: 2,
name: 'Mark Dorey',
title: '\u003cp\u003e\u003cspan\u003eDiscipline Manager (Process, Subsea, Project, Safety)\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eWhen I joined company I started as a resourcing specialist and worked across Search and ...',
image: 'mark.jpg'
}, {
id: 3,
name: 'Sadia Butt',
title: '\u003cp\u003e\u003cspan\u003eDiscipline Manager (Mechanical, Piping, Structural)\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI couldn\u0026rsquo;t have asked for a better company to work for! After working as a resourc...',
image: 'sadia.jpg'
}, {
id: 4,
name: 'Samantha Linnert',
title: '\u003cp\u003e\u003cspan\u003ePayroll Assistant\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI began at company as an operations assistant learning to spec CVs and post jobs. Shortl...',
image: 'samantha.jpg'
}, {
id: 5,
name: 'Simon Cottenham',
title: '\u003cp\u003e\u003cspan\u003eConsultant, Middle East\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI have been with company for exactly one year now, I never would have believed that I wo...',
image: 'simon.jpg'
}, {
id: 6,
name: 'Vicky Spencer',
title: '\u003cp\u003e\u003cspan\u003ePayroll Manager\u003c/span\u003e\u003c/p\u003e',
bio: '\u003cp\u003eI started my career at company in July 2012 initially covering maternity leave, managing...',
image: 'vicky.jpg'
});
$(function () {
listTicker({
list: textlist,
startIndex: 0,
trickerPanel: $('.textbox'),
interval: 3 * 1000,
});
});
you are adding object to a html .... use . operator to get the actual values
....
options.trickerPanel.fadeOut(function () {
$(this).html(value.id).fadeIn();
//--------^^^----here
}
i am taking id from the object and showing it in the div.. you can add whatever you need there..
$(this).html(value.title).fadeIn(); //to get title
fiddle here
$.each(textlist, function(index, value){
//do stuff with your array
});
Pasting just the diff, i tried to get the data here below.
From the code above.
options.trickerPanel.fadeOut(function () {
$(this).html(value).fadeIn();
});
The diff,
options.trickerPanel.fadeOut(function () {
$(this).html(value.bio).fadeIn();
});
The difference, is value is the entire array object being passed to the fadeOut function, accessing each elements in the array gives the result.

Categories

Resources