//
// Copyright © 2011-2025 Cambridge Intelligence Limited.
// All rights reserved.
//
// Sample Code
//
//! Explore different layout options for displaying data.
import KeyLines from "keylines";
import { data } from "./layouts-data.js";
let chart;
const orientationEl = document.getElementById("orientation");
const tightnessEl = document.getElementById("slider");
// Gets the top nodes for Radial and Hierarchy layouts if no nodes are selected
function getTopNodes() {
const selectedItemsIds = chart
.selection()
.filter((item) => chart.getItem(item).type === "node");
return selectedItemsIds.length ? selectedItemsIds : ["2", "5"];
}
// Gets the selected layout name
function getLayoutName() {
return document.querySelector('input[name="layoutName"]:checked').value;
}
function layout() {
// Use the currently selected layout name and options for the layout
const layoutName = getLayoutName();
const orientation = orientationEl.options[orientationEl.selectedIndex].value;
const tightness = parseFloat(tightnessEl.value);
let options;
switch (layoutName) {
case "radial":
options = { top: getTopNodes(), tightness };
break;
case "hierarchy":
options = { top: getTopNodes(), orientation, tightness };
break;
case "sequential":
options = { top: getTopNodes(), orientation, tightness };
break;
default:
options = { tightness };
break;
}
chart.layout(layoutName, options);
}
function initialiseInteractions() {
// Run a layout based on current selected menu options
document.getElementById("layout").addEventListener("click", layout);
// Run applicable layout when orientation selection changes
orientationEl.addEventListener("change", () => {
const layoutName = getLayoutName();
if (layoutName === "hierarchy" || layoutName === "sequential") {
layout();
}
});
// Run a layout when tightness selection changes and update the menu display
tightnessEl.addEventListener("change", () => {
const tightnessValue = tightnessEl.value;
document.getElementById("tightnessValue").innerHTML = ` ${tightnessValue}`;
layout();
});
}
async function loadKeyLines() {
const options = {
drag: {
links: false,
},
logo: { u: "/images/Logo.png" },
handMode: true,
};
chart = await KeyLines.create({ container: "klchart", options });
chart.load(data);
chart.layout();
initialiseInteractions();
}
window.addEventListener("DOMContentLoaded", loadKeyLines);
<!DOCTYPE html>
<html lang="en" style="background-color: #2d383f;">
<head>
<meta charset="UTF-8">
<title>Layouts</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="/layouts.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="/layouts.js" crossorigin="use-credentials" defer 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%;">Layouts</text>
</svg>
</div>
<div class="tab-content-panel" data-tab-group="rhs">
<div class="toggle-content is-visible tabcontent" id="controlsTab">
<p>Try out different layouts by selecting one from the list below.</p>
<form autocomplete="off" onsubmit="return false" id="rhsForm">
<div class="cicontent">
<legend>Layout Name</legend>
<fieldset id="layoutfieldset">
<label class="radio">
<input type="radio" name="layoutName" value="organic" checked="checked"> Organic
</label>
<label class="radio">
<input type="radio" name="layoutName" value="sequential"> Sequential
</label>
<label class="radio">
<input type="radio" name="layoutName" value="hierarchy"> Hierarchy
</label>
<label class="radio">
<input type="radio" name="layoutName" value="lens"> Lens
</label>
<label class="radio">
<input type="radio" name="layoutName" value="radial"> Radial
</label>
<label class="radio">
<input type="radio" name="layoutName" value="structural"> Structural
</label>
</fieldset>
<fieldset>
<input class="btn" type="button" value="Run layout" id="layout">
</fieldset>
<fieldset>
<legend>Options</legend>
</fieldset>
<fieldset>
<label>Tightness:<strong id="tightnessValue"> 5</strong>
<input id="slider" type="range" min="0" max="10" value="5">
</label>
</fieldset>
<fieldset>
<label>Orientation (Hierarchy and Sequential)</label>
<select class="input-block-level" id="orientation">
<option value="down">Down</option>
<option value="right">Right</option>
<option value="up">Up</option>
<option value="left">Left</option>
</select>
</fieldset>
</div>
</form>
</div>
</div>
</div>
</div>
<div id="moreParent">
<div id="moreContainer">
</div>
</div>
<div id="lazyScripts">
</div>
</body>
</html>
input[type=range] {
width: 100%;
margin-bottom: 10px;
}
.label-alpha, .label-beta {
margin-left: 12px;
}
#layoutfieldset {
margin-left:10px;
}
fieldset {
width: 90%;
margin-top:5px;
}
fieldset .radio {
display: block;
padding-left: 0px;
}
Loading source
