//
// Copyright © 2011-2025 Cambridge Intelligence Limited.
// All rights reserved.
//
// Sample Code
//! Use dependency analysis to find relations in hierarchies.
import KeyLines from "keylines";
import { chartData } from "./dependencies-data.js";
// declaring global vars
let chart;
function getOrientation() {
const selection = chart.selection();
if (selection.length > 0) {
const item = chart.getItem(selection[0]);
if (item.type === "node" && item.d.type === "person") {
return "down";
}
}
return "up";
}
function findConnected(ids) {
// merge all the distances: we do not care about metrics here, but only if a node is reachable
let items = [];
const list = chart.getItem(ids);
list.forEach((item) => {
if (item.type === "node") {
const direction = item.d.type === "company" ? "to" : "from";
// merge results
items = items.concat(
Object.keys(chart.graph().distances(item.id, { direction }))
);
}
});
return items;
}
async function filterConnected(id) {
chart.lock(true);
const ids = [id, ...chart.selection()];
const items = findConnected(ids);
await chart.filter((item) => items.includes(item.id), { type: "node" });
await chart.layout("sequential", { top: ids, orientation: getOrientation() });
chart.lock(false);
}
async function restoreAndShowAll() {
chart.lock(true);
chart.selection([]);
await chart.filter(() => true, { time: 500 });
chart.layout("organic", { consistent: true, tightness: 2 });
await chart.zoom("fit", { time: 500, animate: true });
chart.lock(false);
}
function onClick({ id }) {
const item = chart.getItem(id);
if (item && item.type === "node") {
filterConnected(id);
}
}
function onDoubleclick({ id, preventDefault }) {
const item = chart.getItem(id);
if (item === null) {
restoreAndShowAll();
}
// disable zoom
preventDefault();
}
async function startKeyLines() {
const imageAlignment = {
"fas fa-user": { dy: -10 },
"fas fa-building": { dy: 2, e: 0.9 },
};
const options = {
logo: { u: "/images/Logo.png" },
linkEnds: { avoidLabels: false },
iconFontFamily: "Font Awesome 5 Free",
imageAlignment,
hover: 5,
handMode: true,
};
chart = await KeyLines.create({ container: "klchart", options });
chart.on("click", onClick);
chart.on("double-click", onDoubleclick);
chart.load(chartData);
await chart.zoom("fit");
chart.layout("organic", { consistent: true, tightness: 2 });
}
function loadKeyLines() {
document.fonts.load('24px "Font Awesome 5 Free"').then(startKeyLines);
}
window.addEventListener("DOMContentLoaded", loadKeyLines);
<!DOCTYPE html>
<html lang="en" style="background-color: #2d383f;">
<head>
<meta charset="UTF-8">
<title>Hierarchical Dependencies</title>
<link rel="stylesheet" type="text/css" href="/css/keylines.css">
<link rel="stylesheet" type="text/css" href="/css/minimalsdk.css">
<link rel="stylesheet" type="text/css" href="/css/sdk-layout.css">
<link rel="stylesheet" type="text/css" href="/css/demo.css">
<link rel="stylesheet" type="text/css" href="/css/fontawesome5/fontawesome.css">
<link rel="stylesheet" type="text/css" href="/css/fontawesome5/solid.css">
<script src="/vendor/jquery.js" defer type="text/javascript"></script>
<script id="keylines" src="/public/keylines.umd.cjs" defer type="text/javascript"></script>
<script src="/dependencies.js" crossorigin="use-credentials" type="module"></script>
</head>
<body>
<div class="chart-wrapper demo-cols">
<div class="tab-content-panel flex1" id="lhs" data-tab-group="rhs">
<div class="toggle-content is-visible" id="lhsVisual" style="width:100%; height: 100%;">
<div class="klchart" id="klchart">
</div>
</div>
</div>
<div class="rhs citext closed" id="demorhscontent">
<div class="title-bar">
<svg viewBox="0 0 360 60" style="max-width: 360px; max-height: 60px; font-size: 24px; font-family: Raleway; flex: 1;">
<text x="0" y="38" style="width: 100%;">Hierarchical Dependencies</text>
</svg>
</div>
<div class="tab-content-panel" data-tab-group="rhs">
<div class="toggle-content is-visible tabcontent" id="controlsTab">
<p>Dependency analysis: who owns what?</p>
<form autocomplete="off" onsubmit="return false" id="rhsForm">
<div class="cicontent">
<fieldset>
<legend>Instructions</legend>
<ol>
<li>Click a person to see what companies they own</li>
<li>Click a company to see who owns it</li>
<li>Double-click on the background of the chart to return to the full network</li>
</ol>
</fieldset>
</div>
</form>
</div>
</div>
</div>
</div>
<div id="moreParent">
<div id="moreContainer">
</div>
</div>
<div id="lazyScripts">
</div>
</body>
</html>
Loading source
