//
//     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