Add hyperlink to nodes in amcharts Force Directed Tree - javascript

I have this amcharts 4 Force Directed Tree as a map for different pages I have on my website. What I want (and could not figure out how despite searching a lot) is that when a user clicks on a node they go to the webpage corresponding to that node. In short, I wonder if I can have a clickable name for nodes? I greatly appreciate any helps. Here is the JavaScript code:
am4core.useTheme(am4themes_dark);
am4core.useTheme(am4themes_animated);
var chart = am4core.create("chartdiv", am4plugins_forceDirected.ForceDirectedTree);
var networkSeries = chart.series.push(new am4plugins_forceDirected.ForceDirectedSeries())
networkSeries.nodes.template.outerCircle.filters.push(new am4core.DropShadowFilter());
networkSeries.dataFields.linkWith = "linkWith";
networkSeries.dataFields.name = "name";
networkSeries.dataFields.id = "name";
networkSeries.dataFields.value = "value";
networkSeries.dataFields.children = "children";
networkSeries.dataFields.color = "color";
networkSeries.dataFields.fixed = "fixed";
networkSeries.nodes.template.propertyFields.x = "x";
networkSeries.nodes.template.propertyFields.y = "y";
networkSeries.links.template.strength = 1;
networkSeries.manyBodyStrength = -20;
networkSeries.centerStrength = 0.4;
networkSeries.nodes.template.label.text = "{name}"
networkSeries.fontSize = 16;
networkSeries.minRadius = 40;
networkSeries.maxRadius = 80;
var nodeTemplate = networkSeries.nodes.template;
nodeTemplate.fillOpacity = 1;
nodeTemplate.label.hideOversized = true;
nodeTemplate.label.truncate = true;
var linkTemplate = networkSeries.links.template;
linkTemplate.strokeWidth = 5;
linkTemplate.distance = 1.5;
nodeTemplate.events.on("out", function (event) {
var dataItem = event.target.dataItem;
dataItem.childLinks.each(function (link) {
link.isHover = false;
})
})
networkSeries.events.on("inited", function() {
networkSeries.animate({
property: "velocityDecay",
to: 0.7
}, 3000);
});
networkSeries.data = [
{
"name":"Complex Networks",
"value":1000,
"color":"#0086ad",
"fixed": true,
x: am4core.percent(50),
y: am4core.percent(10),
"children":[
{
"name":"Theory \n and Model",
"value":600,
"color":"#0086ad",
"fixed": true,
x: am4core.percent(20),
y: am4core.percent(20),
"children":[
{
"name":"Statistical \n Physics \n Approach",
"value":600,
"color":"#36896E"
},
{
"name":"Balance Theory \n Approach",
"value":600,
"color":"#36896E"
},
{
"name":"Topological \n Data \n Analysis",
"value":400,
"color":"#36896E"
},
{
"name": "Aged \n Networks",
"value": 200,
"color":"#36896E"
},
{
"name": "Dark \n Networks",
"value": 100,
"color":"#36896E"
}
]
},
{
"name":"Application \n and Real-data",
"color":"#0086ad",
"fixed": true,
x: am4core.percent(80),
y: am4core.percent(20),
"value":600,
"children":[
{
"name": "Cancer \n Project",
"value": 100,
"color":"#36896E",
"linkWith":[
"Balance Theory \n Approach"
]
},
{
"name": "Social Data",
"value": 200,
"color":"#8b225b",
"fixed": true,
x: am4core.percent(80),
y: am4core.percent(33),
"children":[
{"name":"Twitter \n Project",
"value":200,
"color":"#36896E"},
{"name":"Complex \n Social \n Systems",
"value":300,
"color":"#36896E"}
]
}
]
}
]
},
{
"name":"Stochastic \n Process",
"value":200,
"color":"#0086ad",
"fixed":true,
x: am4core.percent(50),
y: am4core.percent(45),
"linkWith":[
"Financial \n Markets",
"Application \n and Real-data"
]
},
{
"name":"Network \n Neuroscience \n and Cognition",
"value":500,
"fixed": true,
x: am4core.percent(35),
y: am4core.percent(45),
"linkWith":[
"Balance Theory \n Approach",
"Application \n and Real-data",
"Topological \n Data \n Analysis",
],
"children":[
{
"name":"Resting-state \n fMRI Networks",
"value":600,
"color":"#36896E",
"url":"https://ccnsd.ir/research_projects/brain_networks/"
}
]
},
{
"name":"Econo-physics",
"value":500,
"fixed": true,
x: am4core.percent(65),
y: am4core.percent(45),
"linkWith":[
"Theory \n and Model",
"Application \n and Real-data"
],
"children":[
{
"name":"Quantum \n Economics",
"value":100,
"color":"#36896E"
},
{
"name":"Financial \n Markets",
"value":100,
"children":[
{"name": "Cryptocurrency",
"value": 500,
"color":"#36896E"},
{"name": "Stock \n Markets",
"value": 500,
"color":"#36896E"}
]
}
]
}
];
And the HTML:
<head>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
body { background-color: #30303d; color: #fff; }
#chartdiv {
width: 100%;
height: 1300px;
}
</style>
</head>
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/plugins/forceDirected.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/dark.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>
Thanks in advance!

You can put click event in each node and use the following code.
Please take note that I used amchart 5 version.
series.nodes.template.events.on("click", function (e) {
switch (e.target.dataItem.dataContext.name) {
case 'Econo-physics':
window.open("https://stackoverflow.com/questions/68037180/add-hyperlink-to-nodes-in-amcharts-force-directed-tree");
}
}

Related

How to load nested json into GoJS Regrouping in JavaScript?

I am trying to convert my json to the GoJs regrouping but I am having difficulties.
The regrouping example is as follows: https://gojs.net/latest/samples/regrouping.html
I am using a recursive function in which I am checking all the elements of json but when converting it to graphics in GoJS it is being interpreted in a limited way dynamic. As you can see:
function navigate() {
var traverse = function(obj, fn) {
for (var key in obj) {
fn.apply(this,[key ,obj[key]]);
if (obj[key] !== null && typeof(obj[key]) == "object") {
traverse(obj[key], fn);
}
}
}
My json is:
{
"breakfast_menu": {
"food": [
{
"name": "Strawberry Belgian Waffles",
"price": "$7.95",
"description": "Light Belgian waffles covered with strawberries and whipped cream",
"calories": 900
},
{
"name": "Berry-Berry Belgian Waffles",
"price": "$8.95",
"description": "Light Belgian waffles covered with an assortment of fresh berries and whipped cream",
"calories": 900
},
{
"name": "French Toast",
"price": "$4.50",
"description": "Thick slices made from our homemade sourdough bread",
"calories": 600
},
{
"name": "Homestyle Breakfast",
"price": "$6.95",
"description": "Two eggs, bacon or sausage, toast, and our ever-popular hash browns",
"calories": 950
}
]
}
}
Here's a complete demo:
<!DOCTYPE html>
<html>
<head>
<title>Nested Groups from tree-structured JSON</title>
<!-- Copyright 1998-2021 by Northwoods Software Corporation. -->
<script src="https://unpkg.com/gojs"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make;
myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"ModelChanged": function(e) { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
document.getElementById("mySavedModel").textContent = e.model.toJson();
}
}
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape, { fill: "white" }),
$(go.Panel, "Table",
{ margin: 4 },
$(go.TextBlock, { row: 0 }, new go.Binding("text", "name")),
$(go.TextBlock, { row: 1 }, new go.Binding("text", "price")),
$(go.TextBlock, { row: 2 }, new go.Binding("text", "calories"),
new go.Binding("stroke", "calories", function(c) { return c > 750 ? "red" : "black"; }))
)
);
var json = {
"breakfast_menu": {
"food": [
{
"name": "Strawberry Belgian Waffles",
"price": "$7.95",
"description": "Light Belgian waffles covered with strawberries and whipped cream",
"calories": 900
},
{
"name": "Berry-Berry Belgian Waffles",
"price": "$8.95",
"description": "Light Belgian waffles covered with an assortment of fresh berries and whipped cream",
"calories": 900
},
{
"name": "French Toast",
"price": "$4.50",
"description": "Thick slices made from our homemade sourdough bread",
"calories": 600
},
{
"name": "Homestyle Breakfast",
"price": "$6.95",
"description": "Two eggs, bacon or sausage, toast, and our ever-popular hash browns",
"calories": 950
}
]
}
};
function flattenJson(json) {
var arr = [];
for (var p in json) {
var d = { key: arr.length, isGroup: true, text: p };
arr.push(d);
var item = json[p];
for (var q in item) {
var d2 = { key: arr.length, isGroup: true, group: d.key, text: q };
arr.push(d2);
var list = item[q];
if (Array.isArray(list)) {
for (var i = 0; i < list.length; i++) {
var d3 = list[i];
d3.key = arr.length;
d3.group = d2.key;
arr.push(d3);
}
}
}
}
return arr;
}
myDiagram.model = new go.GraphLinksModel(flattenJson(json));
}
</script>
</head>
<body onload="init()">
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
<textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
</body>
</html>
Without even bothering to define a custom Group template, this produces:
Of course in your app you'll want to define your own group templates.
And you can remove the "ModelChanged" listener which is just here to show you the model resulting from calling flattenJson on your data.

How to validate for un-connected edges to cell in mxgraph

Hi i'm facing problem with validation for un-connected edges to cells in mxgraph
below image will show you my expectation:
Question: whenever i press validate button un-connected edges and cells must be highlighted with red color.
For full view Codepen:https://codepen.io/eabangalore/pen/pmELpL?editors=1100
NOTE: PLEASE SEE CODEPEN LINK (https://codepen.io/eabangalore/pen/pmELpL?editors=1100) as BELOW CODE IS NOT WORKING
Full Code:
<!--
Copyright (c) 2006-2013, JGraph Ltd
Dynamic toolbar example for mxGraph. This example demonstrates changing the
state of the toolbar at runtime.
-->
<html>
<head>
<title>Toolbar example for mxGraph</title>
<!-- Sets the basepath for the library if not in same directory -->
<script type="text/javascript">
mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
function setGraphData(){
var graphState ={"tagName":"mxGraphModel","children":[{"tagName":"root","children":[{"tagName":"mxCell","attributes":{"id":"0"}},{"tagName":"mxCell","attributes":{"id":"1","parent":"0"}},{"tagName":"mxCell","attributes":{"id":"2","value":"A","style":"","parent":"1","vertex":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"271.56251525878906","y":"82.44792175292969","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"3","value":"B","style":"","parent":"1","vertex":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"678.2291717529297","y":"106.89236450195312","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"4","value":"Bangalore","parent":"1","edge":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"0.0511","y":"-20","relative":"1","as":"geometry"},"children":[{"tagName":"mxPoint","attributes":{"x":"370.06251525878906","y":"109.95338610053051","as":"sourcePoint"}},{"tagName":"mxPoint","attributes":{"x":"676.7291717529297","y":"128.3869001543523","as":"targetPoint"}},{"tagName":"mxPoint","attributes":{"as":"offset"}}]}]},{"tagName":"mxCell","attributes":{"id":"5","value":"C","style":"","parent":"1","vertex":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"1013.7847747802734","y":"83.55902862548828","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"6","parent":"1","source":"3","target":"5","edge":"1"},"children":[{"tagName":"mxGeometry","attributes":{"relative":"1","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"7","value":"Not Connected","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"552","y":"267.640625","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"8","value":"Edge Not connected must highlight in red color","edge":"1","parent":"1","source":"5"},"children":[{"tagName":"mxGeometry","attributes":{"relative":"1","as":"geometry"},"children":[{"tagName":"mxPoint","attributes":{"x":"740","y":"260","as":"targetPoint"}}]}]}]}]};
localStorage.setItem('graphState',JSON.stringify(graphState));
}
function html2json(html){
if(html.nodeType==3){
return {
"tagName":"#text",
"content":html.textContent
}
}
var element = {
"tagName":html.tagName
};
if(html.getAttributeNames().length>0){
element.attributes = html.getAttributeNames().reduce(
function(acc,at){acc[at]=html.getAttribute(at); return acc;},
{}
);
}
if(html.childNodes.length>0){
element.children = Array.from(html.childNodes)
.filter(
function(el){
return el.nodeType!=3
||el.textContent.trim().length>0
})
.map(function(el){return html2json(el);});
}
return element;
}
function json2html(json){
var xmlDoc = document.implementation.createDocument(null, json.tagName);
var addAttributes = function(jsonNode, node){
if(jsonNode.attributes){
Object.keys(jsonNode.attributes).map(
function(name){
node.setAttribute(name,jsonNode.attributes[name]);
}
);
}
}
var addChildren = function(jsonNode,node){
if(jsonNode.children){
jsonNode.children.map(
function(jsonChildNode){
json2htmlNode(jsonChildNode,node);
}
);
}
}
var json2htmlNode = function(jsonNode,parent){
if(jsonNode.tagName=="#text"){
return xmlDoc.createTextNode(jsonNode.content);
}
var node = xmlDoc.createElement(jsonNode.tagName);
addAttributes(jsonNode,node);
addChildren(jsonNode,node);
parent.appendChild(node);
}
addAttributes(json,xmlDoc.firstElementChild);
addChildren(json,xmlDoc.firstElementChild);
return xmlDoc;
}
</script>
<!-- Loads and initializes the library -->
<script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
<!-- Example code -->
<script type="text/javascript">
// Program starts here. Creates a sample graph in the
// DOM node with the specified ID. This function is invoked
// from the onLoad event handler of the document (see below).
function main()
{
setGraphData();
// Checks if browser is supported
if (!mxClient.isBrowserSupported())
{
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
}
else
{
// Defines an icon for creating new connections in the connection handler.
// This will automatically disable the highlighting of the source vertex.
mxConnectionHandler.prototype.connectImage = new mxImage('images/connector.gif', 16, 16);
// Creates the div for the toolbar
var tbContainer = document.createElement('div');
tbContainer.style.position = 'absolute';
tbContainer.style.overflow = 'hidden';
tbContainer.style.padding = '2px';
tbContainer.style.left = '0px';
tbContainer.style.top = '0px';
tbContainer.style.width = '24px';
tbContainer.style.bottom = '0px';
document.body.appendChild(tbContainer);
// Creates new toolbar without event processing
var toolbar = new mxToolbar(tbContainer);
toolbar.enabled = false
// Creates the div for the graph
var container = document.createElement('div');
container.style.position = 'absolute';
container.style.overflow = 'hidden';
container.style.left = '24px';
container.style.top = '0px';
container.style.right = '0px';
container.style.bottom = '0px';
container.style.background = 'url("editors/images/grid.gif")';
document.body.appendChild(container);
// Workaround for Internet Explorer ignoring certain styles
if (mxClient.IS_QUIRKS)
{
document.body.style.overflow = 'hidden';
new mxDivResizer(tbContainer);
new mxDivResizer(container);
}
// Creates the model and the graph inside the container
// using the fastest rendering available on the browser
var model = new mxGraphModel();
var graph = new mxGraph(container, model);
// Enables new connections in the graph
graph.setConnectable(true);
graph.setMultigraph(false);
// Stops editing on enter or escape keypress
var keyHandler = new mxKeyHandler(graph);
var rubberband = new mxRubberband(graph);
var addVertex = function(icon, w, h, style)
{
var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
vertex.setVertex(true);
var img = addToolbarItem(graph, toolbar, vertex, icon);
img.enabled = true;
graph.getSelectionModel().addListener(mxEvent.CHANGE, function()
{
var tmp = graph.isSelectionEmpty();
mxUtils.setOpacity(img, (tmp) ? 100 : 20);
img.enabled = tmp;
});
};
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rectangle.gif', 100, 40, '');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rounded.gif', 100, 40, 'shape=rounded');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/ellipse.gif', 40, 40, 'shape=ellipse');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rhombus.gif', 40, 40, 'shape=rhombus');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/triangle.gif', 40, 40, 'shape=triangle');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/cylinder.gif', 40, 40, 'shape=cylinder');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/actor.gif', 30, 40, 'shape=actor');
// read state on load
if(window.localStorage.graphState){
var doc = json2html(JSON.parse(localStorage.graphState));
var dec = new mxCodec(doc);
dec.decode(doc.documentElement, graph.getModel());
}
// save state on change
graph.getModel().addListener('change',function(){
var codec = new mxCodec();
window.localStorage.graphState = JSON.stringify(html2json(codec.encode(
graph.getModel()
)));
});
}
}
function addToolbarItem(graph, toolbar, prototype, image)
{
// Function that is executed when the image is dropped on
// the graph. The cell argument points to the cell under
// the mousepointer if there is one.
var funct = function(graph, evt, cell, x, y)
{
graph.stopEditing(false);
var vertex = graph.getModel().cloneCell(prototype);
vertex.geometry.x = x;
vertex.geometry.y = y;
graph.addCell(vertex);
graph.setSelectionCell(vertex);
}
// Creates the image which is used as the drag icon (preview)
var img = toolbar.addMode(null, image, function(evt, cell)
{
var pt = this.graph.getPointForEvent(evt);
funct(graph, evt, cell, pt.x, pt.y);
});
// Disables dragging if element is disabled. This is a workaround
// for wrong event order in IE. Following is a dummy listener that
// is invoked as the last listener in IE.
mxEvent.addListener(img, 'mousedown', function(evt)
{
// do nothing
});
// This listener is always called first before any other listener
// in all browsers.
mxEvent.addListener(img, 'mousedown', function(evt)
{
if (img.enabled == false)
{
mxEvent.consume(evt);
}
});
mxUtils.makeDraggable(img, graph, funct);
return img;
}
</script>
</head>
<!-- Calls the main function after the page has loaded. Container is dynamically created. -->
<body onload="main();" >
</body>
</html>
Please help me thanks in advance!!!
Edit: As per the comment, to validate the cells not connected to the parent cell or its branches, we can use a recursive function checking each connected edge starts from the parent cell and so on.
Due to the limit of characters, the original code snippet is removed.
.not_connected * {
color: red;
font-color: red;
stroke: red;
stroke-color: red;
}
<!--
Copyright (c) 2006-2013, JGraph Ltd
Dynamic toolbar example for mxGraph. This example demonstrates changing the
state of the toolbar at runtime.
-->
<html>
<head>
<title>Toolbar example for mxGraph</title>
</head>
<!-- Calls the main function after the page has loaded. Container is dynamically created. -->
<body onload="main();">
<button style="position:absolute; left:300px;padding:8px 40px;background:orangered;color:#fff;outline:none;border:none;z-index:100;" id="validate_btn">Validate</button>
</body>
</html>
<!-- Sets the basepath for the library if not in same directory -->
<script type="text/javascript">
mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
var graphStateJSON;
var graph;
function setGraphData() {
var graphState = {
"tagName": "mxGraphModel",
"children": [{
"tagName": "root",
"children": [{
"tagName": "mxCell",
"attributes": {
"id": "0"
}
}, {
"tagName": "mxCell",
"attributes": {
"id": "1",
"parent": "0"
}
}, {
"tagName": "mxCell",
"attributes": {
"id": "2",
"value": "A",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "460",
"y": "80",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "3",
"value": "C",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "460",
"y": "190",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "4",
"edge": "1",
"parent": "1",
"source": "2",
"target": "3"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"relative": "1",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "5",
"value": "B",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "280",
"y": "190",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "6",
"value": "D",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "663",
"y": "193",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "7",
"edge": "1",
"parent": "1",
"source": "2",
"target": "5"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"relative": "1",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "8",
"edge": "1",
"parent": "1",
"source": "2",
"target": "6"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"relative": "1",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "9",
"value": "E",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "660",
"y": "260",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "10",
"edge": "1",
"parent": "1",
"source": "6",
"target": "9"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"relative": "1",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "11",
"value": "F",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "280",
"y": "260",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "12",
"value": "G",
"style": "",
"vertex": "1",
"parent": "1"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"x": "459",
"y": "257",
"width": "100",
"height": "40",
"as": "geometry"
}
}]
}, {
"tagName": "mxCell",
"attributes": {
"id": "13",
"edge": "1",
"parent": "1",
"source": "11",
"target": "12"
},
"children": [{
"tagName": "mxGeometry",
"attributes": {
"relative": "1",
"as": "geometry"
}
}]
}]
}]
};
graphStateJSON = JSON.stringify(graphState);
}
function html2json(html) {
if (html.nodeType == 3) {
return {
"tagName": "#text",
"content": html.textContent
}
}
var element = {
"tagName": html.tagName
};
if (html.getAttributeNames().length > 0) {
element.attributes = html.getAttributeNames().reduce(
function(acc, at) {
acc[at] = html.getAttribute(at);
return acc;
}, {}
);
}
if (html.childNodes.length > 0) {
element.children = Array.from(html.childNodes)
.filter(
function(el) {
return el.nodeType != 3 ||
el.textContent.trim().length > 0
})
.map(function(el) {
return html2json(el);
});
}
return element;
}
function json2html(json) {
var xmlDoc = document.implementation.createDocument(null, json.tagName);
var addAttributes = function(jsonNode, node) {
if (jsonNode.attributes) {
Object.keys(jsonNode.attributes).map(
function(name) {
node.setAttribute(name, jsonNode.attributes[name]);
}
);
}
}
var addChildren = function(jsonNode, node) {
if (jsonNode.children) {
jsonNode.children.map(
function(jsonChildNode) {
json2htmlNode(jsonChildNode, node);
}
);
}
}
var json2htmlNode = function(jsonNode, parent) {
if (jsonNode.tagName == "#text") {
return xmlDoc.createTextNode(jsonNode.content);
}
var node = xmlDoc.createElement(jsonNode.tagName);
addAttributes(jsonNode, node);
addChildren(jsonNode, node);
parent.appendChild(node);
}
addAttributes(json, xmlDoc.firstElementChild);
addChildren(json, xmlDoc.firstElementChild);
return xmlDoc;
}
</script>
<!-- Loads and initializes the library -->
<script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
<!-- Example code -->
<script type="text/javascript">
// Program starts here. Creates a sample graph in the
// DOM node with the specified ID. This function is invoked
// from the onLoad event handler of the document (see below).
var graph;
var graphView;
var notConnectedCells = [];
var parentCellId = "2";
function main() {
setGraphData();
// Checks if browser is supported
if (!mxClient.isBrowserSupported()) {
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
} else {
// Defines an icon for creating new connections in the connection handler.
// This will automatically disable the highlighting of the source vertex.
mxConnectionHandler.prototype.connectImage = new mxImage('images/connector.gif', 16, 16);
// Creates the div for the toolbar
var tbContainer = document.createElement('div');
tbContainer.style.position = 'absolute';
tbContainer.style.overflow = 'hidden';
tbContainer.style.padding = '2px';
tbContainer.style.left = '0px';
tbContainer.style.top = '0px';
tbContainer.style.width = '24px';
tbContainer.style.bottom = '0px';
document.body.appendChild(tbContainer);
// Creates new toolbar without event processing
var toolbar = new mxToolbar(tbContainer);
toolbar.enabled = false
// Creates the div for the graph
var container = document.createElement('div');
container.style.position = 'absolute';
container.style.overflow = 'hidden';
container.style.left = '24px';
container.style.top = '0px';
container.style.right = '0px';
container.style.bottom = '0px';
container.style.background = 'url("editors/images/grid.gif")';
document.body.appendChild(container);
// Workaround for Internet Explorer ignoring certain styles
if (mxClient.IS_QUIRKS) {
document.body.style.overflow = 'hidden';
new mxDivResizer(tbContainer);
new mxDivResizer(container);
}
// Creates the model and the graph inside the container
// using the fastest rendering available on the browser
var model = new mxGraphModel();
graph = new mxGraph(container, model);
// Enables new connections in the graph
graph.setConnectable(true);
graph.setMultigraph(false);
// Stops editing on enter or escape keypress
var keyHandler = new mxKeyHandler(graph);
var rubberband = new mxRubberband(graph);
var addVertex = function(icon, w, h, style) {
var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
vertex.setVertex(true);
var img = addToolbarItem(graph, toolbar, vertex, icon);
img.enabled = true;
graph.getSelectionModel().addListener(mxEvent.CHANGE, function() {
var tmp = graph.isSelectionEmpty();
mxUtils.setOpacity(img, (tmp) ? 100 : 20);
img.enabled = tmp;
});
};
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rectangle.gif', 100, 40, '');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rounded.gif', 100, 40, 'shape=rounded');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/ellipse.gif', 40, 40, 'shape=ellipse');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rhombus.gif', 40, 40, 'shape=rhombus');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/triangle.gif', 40, 40, 'shape=triangle');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/cylinder.gif', 40, 40, 'shape=cylinder');
addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/actor.gif', 30, 40, 'shape=actor');
// read state on load
if (graphStateJSON) {
var doc = json2html(JSON.parse(graphStateJSON));
var dec = new mxCodec(doc);
dec.decode(doc.documentElement, graph.getModel());
}
// save state on change
graph.getModel().addListener('change', function() {
var codec = new mxCodec();
graphStateJSON = JSON.stringify(html2json(codec.encode(
graph.getModel()
)));
});
}
}
function addToolbarItem(graph, toolbar, prototype, image) {
// Function that is executed when the image is dropped on
// the graph. The cell argument points to the cell under
// the mousepointer if there is one.
var funct = function(graph, evt, cell, x, y) {
graph.stopEditing(false);
var vertex = graph.getModel().cloneCell(prototype);
vertex.geometry.x = x;
vertex.geometry.y = y;
graph.addCell(vertex);
graph.setSelectionCell(vertex);
}
// Creates the image which is used as the drag icon (preview)
var img = toolbar.addMode(null, image, function(evt, cell) {
var pt = this.graph.getPointForEvent(evt);
funct(graph, evt, cell, pt.x, pt.y);
});
// Disables dragging if element is disabled. This is a workaround
// for wrong event order in IE. Following is a dummy listener that
// is invoked as the last listener in IE.
mxEvent.addListener(img, 'mousedown', function(evt) {
// do nothing
});
// This listener is always called first before any other listener
// in all browsers.
mxEvent.addListener(img, 'mousedown', function(evt) {
if (img.enabled == false) {
mxEvent.consume(evt);
}
});
mxUtils.makeDraggable(img, graph, funct);
return img;
}
function Validate(mxCell){
let isConnected = true;
// check each cell that each edge connected to
for(let i=0;i<mxCell.getEdgeCount();i++){
let edge = mxCell.getEdgeAt(i);
if(edge.target === null) continue; // no target
if(mxCell.getId() === edge.target.getId()) continue; // target is mxCell itself
isConnected = edge.source !== null && edge.target !== null;
if(isConnected){
// remove source cell if found and so on
let sourceIndex = notConnectedCells.findIndex(c=>c.id === edge.source.getId());
if(sourceIndex !== -1) notConnectedCells.splice(sourceIndex,1);
let targetIndex = notConnectedCells.findIndex(c=>c.id === edge.target.getId());
if(targetIndex !== -1) notConnectedCells.splice(targetIndex,1);
let edgeIndex = notConnectedCells.findIndex(c=>c.id === edge.getId());
if(edgeIndex !== -1) notConnectedCells.splice(edgeIndex,1);
// check next cell and its edges
Validate(edge.target);
}
}
}
function ResetColor(state){
state.shape.node.classList.remove("not_connected");
if(state.text)
state.text.node.classList.remove("not_connected");
}
function SetNotConnectedColor(state){
for(let i=0;i<notConnectedCells.length;i++){
let mxCell = notConnectedCells[i];
let state = graphView.getState(mxCell);
state.shape.node.classList.add("not_connected");
if(state.text)
state.text.node.classList.add("not_connected");
}
}
document.querySelector("#validate_btn").addEventListener("click", function() {
let cells = graph.getModel().cells;
graphView = graph.getView();
notConnectedCells.length = 0;
// create an array of cells and reset the color
for(let key in cells){
if(!cells.hasOwnProperty(key)) continue;
let mxCell = cells[key];
if(!mxCell.isVertex() && !mxCell.isEdge()) continue;
notConnectedCells.push(mxCell);
let state = graphView.getState(mxCell);
ResetColor(state);
}
// starts with the parent cell
let parentCell = notConnectedCells.find(c=>c.id === parentCellId);
Validate(parentCell);
SetNotConnectedColor();
})
</script>
First, set graph to a global variable. (var graph = new mxGraph(container, model);)
Then, get all cells(as an object) and graphView from graph and iterate all the cells checking if it's connected or not.
function Validate(){
let cells = graph.getModel().cells;
let graphView = graph.getView();
for(let key in cells){
if(!cells.hasOwnProperty(key)) continue;
let mxCell = cells[key];
if(!mxCell.isVertex() && !mxCell.isEdge()) continue;
let state = graphView.getState(mxCell);
ResetColor(state);
let notConnected = true;
if(mxCell.isVertex()){
for(let i=0;i<mxCell.getEdgeCount();i++){
let edge = mxCell.getEdgeAt(i);
// if any of an edge connected to both source and target, it's connected
if(edge.source !== null && edge.target !== null){
notConnected = false;
break;
}
}
}
else { // mxCell.isEdge()
notConnected = mxCell.source === null || mxCell.target === null;
}
if(notConnected) SetNotConnectedColor(state);
}
}
function ResetColor(state){
state.shape.node.classList.remove("not_connected");
if(state.text)
state.text.node.classList.remove("not_connected");
}
function SetNotConnectedColor(state){
state.shape.node.classList.add("not_connected");
if(state.text)
state.text.node.classList.add("not_connected");
}
document.querySelector("#validate_btn").addEventListener("click", function(){
Validate();
})
And here's the localStorage version code if you want(codepen)

Jspdf-autotable Rowspan Fix

I have been generating PDF using Jspdf and Jspdf-autotable plugin. Check this code that I am using to make my customized pdf -
import React, { Component } from 'react';
import jsPDF from "jspdf";
import autotable from "jspdf-autotable";
var getColumns = function () {
return [
{ title: "Student", dataKey: "studentName" },
{ title: "Gender", dataKey: "studentGender" },
{ title: "Mother Name", dataKey: "motherName" },
{ title: "Father Name", dataKey: "fatherName" }
]
};
var getData = function () {
return rows
};
var rows;
class FeaturePage extends Component {
constructor() {
super();
this.exportpdf = this.exportpdf.bind(this);
this.state = {
sales: [
{
"studentId": "100122000116",
"name": "hasan",
"customStudentId": "1510020",
"studentName": "Tasnim Tabassum",
"studentGender": "Female",
"studentDOB": "2012-07-27",
"studentReligion": "Islam",
"motherName": "Sb",
"fatherName": "Md. Mamunar Rashid"
},
{
"studentId": "100122000116",
"name": "hasan",
"customStudentId": "1510020",
"studentName": "Star",
"studentGender": "Female",
"studentDOB": "2012-07-27",
"studentReligion": "Islam",
"motherName": "Sd",
"fatherName": "Md. Mamunar Rashid"
},
{
"studentId": "100122000116",
"name": "arif",
"customStudentId": "1510020",
"studentName": "Tasnim Tabassum",
"studentGender": "Female",
"studentDOB": "2012-07-27",
"studentReligion": "Islam",
"motherName": "safd",
"fatherName": "Md. Mamunar Rashid"
},
{
"studentId": "100122000216",
"name": "arif",
"customStudentId": "1510000",
"studentName": "Star2",
"studentGender": "Female",
"studentDOB": "2012-06-30",
"studentReligion": "Islam",
"motherName": "Mst. Fawalia Akter",
"fatherName": "Md. Azaharul Islam"
}
]
};
}
exportpdf() {
var doc = new jsPDF('p', 'pt');
doc.autoTable(getColumns(), getData(), {
theme: 'grid',
startY: 60,
drawRow: function (row, data) {
if (data.row.raw.name) {
doc.autoTableText(data.row.raw.name, data.settings.margin.left + data.table.width / 2, row.y + row.height / 2, {
halign: 'center',
valign: 'middle'
}
);
data.cursor.y += 20;
}
},
});
doc.save('Student List.pdf');
}
render() {
rows = this.state.sales;
return (
<div>
<button onClick={this.exportpdf} className="exportPDF">Export to PDF</button>
</div>
);
}
}
export default FeaturePage;
And it is generating this pdf
But I want to generate something like this one
How can I do that. I have tried out all the hooks that i Read in the documentation , but nonetheless couldn't make it work the way i want it.

Json data not able to display as a graph using sigma.js

I'm using this code to display JSON file data as a graph but it is not displaying anything.
How to display this JSON data using sigma.js in graph form.
Any pointers would be appreciated!
Code
var data = {
"UniversalWord": {
"UniversalWord": [{
"uw_id": 1,
"HeadWord": {
"word": "aare"
},
"Restriction": {
"SemanticRelations": {
"feat": [{
"att": "restriction_type",
"value": "iof"
},
{
"att": "target",
"val": " "
}
]
}
},
"NLDescription": {
"Gloss": {
"feat": {
"att": "Description",
"val": "\"A RIVER IN NORTH CENTRAL SWITZERLAND THAT RUNS NORTHEAST INTO THE RHINE\""
}
},
"Lemma": {
"feat": {
"att": "word",
"val": "aare"
}
},
"Example": {
"feat": {
"att": "description",
"val": "\"\""
}
}
},
"MetaInfo": {
"Frequency": {
"freq": ""
},
"UWSource": {
"Source_id": "WORDNET"
}
}
}]
}
}
// these are just some preliminary settings
var g = {
nodes: [],
edges: []
};
// Create new Sigma instance in graph-container div (use your div name here)
s = new sigma({
graph: g,
container: 'graph-container',
renderer: {
container: document.getElementById('graph-container'),
type: 'canvas'
},
settings: {
minNodeSize: 8,
maxNodeSize: 16
}
});
// first you load a json with (important!) s parameter to refer to the sigma instance
sigma.parsers.json(
//'test.json',
data,
s,
function() {
// this below adds x, y attributes as well as size = degree of the node
var i,
nodes = s.graph.nodes(),
len = nodes.length;
for (i = 0; i < len; i++) {
nodes[i].x = Math.random();
nodes[i].y = Math.random();
nodes[i].size = s.graph.degree(nodes[i].id);
nodes[i].color = nodes[i].center ? '#333' : '#666';
}
// Refresh the display:
s.refresh();
// ForceAtlas Layout
s.startForceAtlas2();
}
);
.link {
fill: none;
stroke: #000;
}
.node {
stroke: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.2.0/sigma.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.2.0/plugins/sigma.parsers.json.min.js"></script>
<div id="graph-container"></div>

Filtering JSON data

I have a JSON file which contains data like the following:
{"posts": [
{ "title":"1", "url":"n1.png" },
{ "title":"2", "url":"n2.png" },
{ "title":"3", "url":"n3.png" },
{ "title":"4", "url":"n4.png" },
{ "title":"5", "url":"n5.png" },
{ "title":"6", "url":"n6.png" },
{ "title":"7", "url":"n7.png" },
{ "title":"8", "url":"n8.png" },
{ "title":"9", "url":"n9.png" },
{ "title":"10", "url":"n10.png" }
]}
I need to filter title by range with two text boxes: from and to.
Why not do this?
var json = JSON.parse('{"posts": [
{ "title":"1", "url":"n1.png" },
{ "title":"2", "url":"n2.png" },
{ "title":"3", "url":"n3.png" },
{ "title":"4", "url":"n4.png" },
{ "title":"5", "url":"n5.png" },
{ "title":"6", "url":"n6.png" },
{ "title":"7", "url":"n7.png" },
{ "title":"8", "url":"n8.png" },
{ "title":"9", "url":"n9.png" },
{ "title":"10", "url":"n10.png" }
]}');
var filteredJson = json.posts.filter(function (row) {
if(row.title matches your criteria) {
return true
} else {
return false;
}
});
Yes, its an ES5 method but that can be shimmed quite nicely
I use Linq JS on my current project and it works really well for filtering data.
http://jslinq.codeplex.com/
var posts = [
{ "title":"1", "url":"n1.png" },
{ "title":"2", "url":"n2.png" },
{ "title":"3", "url":"n3.png" },
{ "title":"4", "url":"n4.png" },
{ "title":"5", "url":"n5.png" },
{ "title":"6", "url":"n6.png" },
{ "title":"7", "url":"n7.png" },
{ "title":"8", "url":"n8.png" },
{ "title":"9", "url":"n9.png" },
{ "title":"10", "url":"n10.png" }
];
var filteredPost = JSLINQ(posts)
.Where(function(item){ return item.title >= "textBox1Value" && item.title <= "textBox2Value"; });
There is another solution to this: using jLinq.js (documentation), which has even more features. In this case, you can get the solution by using the following code:
var selectedPosts = jLinq.from(posts)
.betweenEquals("title",4,8)
.select();
try this
var q = new RegExp(req.query.q,'i');
posts = posts.filter(function(item){
if(item.title.match(q) || item.url.match(q)){
return item;
}
});
Read the json into an object/arr the parseJson function of jquery(http://api.jquery.com/jQuery.parseJSON/) and the try to splice the array using the splice function() Just make a copy of the object and splice that one.
Well i have this JSON array full of projects, each of project belong to a product:
[
{
"id": 1,
"parentProduct": {
"id": 12,
"productName": "Test 123"
},
"phase": "Phase 4",
"productNumber": "111223",
"projectName": "Test JPEG Apple",
"supplier1": "de",
},
{
"id": 2,
"parentProduct": {
"id": 12,
"productName": "Test from me"
},
"phase": "222",
"productNumber": "11122",
"projectName": "Test PNG",
"supplier1": "222"
}
]
I wanted to get only those with specific parent id, and i did it as below:
filterByProductId(projects, productId) : any[] {
var filteredArray = new Array;
for(var k in projects) {
if(projects[k].parentProduct.id == productId) {
filteredArray.push(projects[k]);
}
}
return filteredArray;
}
json data array of objects filter
<html>
<head>
<script type="text/javascript">
/*
var ss = JOSN.stringify(obj,function(key,value){ //serialization
if(key=='a'){
return undefined;
}else{
return value;
}
});
*/
var jsonStr = [
{
"name": "Bang Bang",
"outline": "A chance encounter with a mysterious charmer leads to a bank employee's wild adventure.",
"rating": 5.6,
"director": "Siddharth Anand",
"id": 250
},
{
"name": "Bang Bang",
"outline": "A chance encounter with a mysterious charmer leads to a bank employee's wild adventure.",
"rating": 5.6,
"director": "Siddharth Anand",
"id": 250
},
{
"name": "Bang Bang",
"outline": "A chance encounter with a mysterious charmer leads to a bank employee's wild adventure.",
"rating": 5.6,
"director": "Siddharth Anand",
"id": 250
},
{
"name": "Indian",
"outline": "After his daughter's tragic death, a freedom fighter steps up his war against corruption.",
"rating": 8.4,
"director": "Shankar",
"id": 251
},
{
"name": "Dilwale Dulhania Le Jayenge",
"outline": "Raj and Simran meet on a trip to Europe. After some initial misadventures, they fall in love. The battle begins to win over two traditional families.",
"rating": 8.4,
"director": "Aditya Chopra",
"id": 253
}
];
var jsonobj = jsonStr;
function filterMovieDirectorData(movie,director){
if(movie!='' && (director!='' && director!='Director')){
var data = jsonobj.filter(function(item){
return (item["name"].toLowerCase().indexOf(movie.toLowerCase())!=-1 && item["director"].toLowerCase().indexOf(director.toLowerCase())!=-1)
});
}else if(movie!='' && director=='Director'){
var data = jsonobj.filter(function(item){
return item["name"].toLowerCase().indexOf(movie.toLowerCase())!=-1
});
}else if(movie=='' && (director!='' && director!='Director')){
var data = jsonobj.filter(function(item){
return item["director"].toLowerCase().indexOf(director.toLowerCase())!=-1
});
}
return data;
}
function getFilterDirectorJson(){
var inputStr = document.getElementById("movie").value;
var e = document.getElementById("director");
var directorStr = e.options[e.selectedIndex].text;
if( (inputStr=='' || inputStr=='Enter movie name') && (directorStr=='' || directorStr=='Director') ){
alert("Please enter movie name or select director.");
document.getElementById("filter_data_div").innerHTML="";
document.getElementById("movie").focus();
return false;
}
var filterObjs = filterMovieDirectorData(inputStr,directorStr);
var text="";
for(var i=0; i<filterObjs.length; i++){
text+='<div id="filter_data"><div><h3>'+filterObjs[0].name+'</h3></div>';
text+='<div>Director : '+filterObjs[0].director+'</div></div><div class="clear"></div>';
}
if(filterObjs.length===0){document.getElementById("filter_data_div").innerHTML='<div id="filter_data"><div><h3>No movies found.</h3></div></div>';}else
document.getElementById("filter_data_div").innerHTML=text;
}
window.onload=function(){
getDirectors();
}
function getDirectors(){
for(var i=0; i<jsonobj.length; i++){
//console.log(jsonobj[i].director);
var option = document.createElement("option");
option.text = jsonobj[i].director;
option.value = i;
var daySelect = document.getElementById('director');
daySelect.appendChild(option);
}
}
</script>
<style>
#director{
line-height: 3px;
padding: 20px;
font-size: 21px;
color: #acacac;
}
#go{
background: #FFC000;
padding: 11px 14px 16px 11px;
font-size: 36px;
line-height: 3;
color: #fff;
margin: 0px;
text-align: center;
}
#movie{
width: 213px;
font-size: 21px;
margin-left: 12px;
padding: 20px;
color:#ACACAC;
}
#main_div{
background: #EEEEEE;
width: 554px;
min-height:120px;
}
#filter_data{
width: 335px;
background: #D8D8D8;
padding: 1px 0px 20px 13px;
margin: 20px 0px 0px 12px;
border: 1px solid #000;
}
a{text-decoration:none;}
.clear{clear: both;}
</style>
</head>
<body>
<div id="main_div">
<div style="display:block;">
<input type="text" id="movie" placeholder="Enter movie name">
<select id="director" ><option value="">Director</option></select>
Go
</div>
<div id="filter_data_div"></div>
</div>
</body>
</html>
First once you have all the json data, you need to traverse them. For that,
**$.each(data, function (i, data) {
if (data.title >= "textBox1Value" && item.title <= "textBox2Value")
//then the data;
});**
List item

Categories

Resources