//
// Copyright © 2011-2025 Cambridge Intelligence Limited.
// All rights reserved.
//
// Sample Code
//
//! Search for text in a chart.
import KeyLines from "keylines";
import { data } from "./search-data.js";
let chart;
const formElement = document.getElementById("rhsForm");
const searchInputElement = document.getElementById("name-search-input");
// Select all nodes with labels containing the search
async function selectMatchingNodes() {
const searchText = searchInputElement.value;
// If there is no search value, clear the selection and return
if (!searchText) {
chart.selection([]);
return;
}
const matchingNodes = [];
// Iterate over every node and test if it matches the search criterion
await chart.each({ type: "node" }, (item) => {
// make both lowercase so we can match better
if (item.t.toLowerCase().includes(searchText.toLowerCase())) {
matchingNodes.push(item.id);
}
});
// Set chart selection to matching nodes
chart.selection(matchingNodes);
}
// Fit the current selection to view and ping selected items
function centreAndPingSelection() {
chart.zoom("selection", { animate: true, time: 300 });
chart.ping(chart.selection());
}
// Search and ping nodes when search is submitted
async function searchAndPing(event) {
event.preventDefault();
await selectMatchingNodes();
centreAndPingSelection();
}
// Attach submit listener for search, and change listener for input field
function initialiseInteractions() {
formElement.addEventListener("submit", searchAndPing);
searchInputElement.addEventListener("input", selectMatchingNodes);
}
async function loadKeyLines() {
const options = {
handMode: true,
logo: { u: "/images/Logo.png" },
linkStyle: { inline: true },
};
chart = await KeyLines.create({ container: "klchart", options });
chart.load(data);
chart.zoom("fit");
initialiseInteractions();
}
window.addEventListener("DOMContentLoaded", loadKeyLines);
<!DOCTYPE html>
<html lang="en" style="background-color: #2d383f;">
<head>
<meta charset="UTF-8">
<title>Search for Text</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">
<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="/search.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%;">Search for Text</text>
</svg>
</div>
<div class="tab-content-panel" data-tab-group="rhs">
<div class="toggle-content is-visible tabcontent" id="controlsTab">
<p>Search for text in charts and move to the items found.</p>
<form autocomplete="off" onsubmit="return false" id="rhsForm">
<div class="cicontent">
<fieldset>
<legend>Search for a name</legend>
<div class="input-append">
<input id="name-search-input" type="text" name="name">
<button class="btn" type="submit" style="margin-top: 0px;">Search</button>
</div>
</fieldset>
<p>Type something and click <code class="black">Search</code> to move the view to matching search items.</p>
</div>
</form>
</div>
</div>
</div>
</div>
<div id="moreParent">
<div id="moreContainer">
</div>
</div>
<div id="lazyScripts">
</div>
</body>
</html>
Loading source
