//
//     Copyright © 2011-2025 Cambridge Intelligence Limited.
//     All rights reserved.
//
//     Sample Code
//
//!    Highlight key items by sending others to the background.
import KeyLines from "keylines";
import { data } from "./background-data.js";

let chart;

const appearanceStyles = {
  Default: {
    selectionColour: "rgb(114, 179, 0)",
    selectedLink: null,
    selectedNode: null,
  },
  Red: {
    selectionColour: "rgb(220,20,60)",
    selectedLink: null,
    selectedNode: null,
  },
  Blue: {
    selectedLink: {
      c: "rgb(0,0,204)",
    },
    selectedNode: {
      b: "rgb(0,0,204)",
      bs: "dashed",
      c: "rgb(0,102,204)",
      ha0: {
        r: 37,
        w: 4,
        c: "rgb(153,204,255)",
      },
    },
  },
};

function createEventHandlers() {
  // Update the background effect when the selection changes
  chart.on("selection-change", () => {
    updateSelection(chart.selection());
  });

  // Apply selection theme and ensure a node selection
  const appearanceEl = document.getElementById("appearance");
  appearanceEl.addEventListener("change", () => {
    const options = appearanceStyles[appearanceEl.value];
    chart.options(options);
    if (chart.selection().length === 0) {
      // If there's no selection, force node 7 to be selected
      updateSelection(chart.selection("7"));
    }
  });
}

function updateSelection(itemIds) {
  const nodeIds = itemIds.filter((id) => !id.match("-"));
  if (nodeIds.length === 0) {
    // Clicked on background - restore all the elements in the foreground
    chart.foreground(() => true);
  } else {
    const selectedItem = chart.getItem(nodeIds);
    // Ensure we have clicked on a node, not the navigation control
    if (selectedItem) {
      // Foreground the selected item and outbound neighbours
      const result = chart.graph().neighbours(nodeIds, { direction: "from" });
      const neighbours = nodeIds.concat(result.nodes, result.links);
      chart.foreground((item) => neighbours.includes(item.id), { type: "all" });
    }
  }
}

async function loadKeyLines() {
  const options = {
    logo: { u: "/images/Logo.png" },
    handMode: true,
  };
  chart = await KeyLines.create({ container: "klchart", options });
  chart.load(data);
  chart.layout("organic", { tightness: 3 });
  createEventHandlers();
}

window.addEventListener("DOMContentLoaded", loadKeyLines);
<!DOCTYPE html>
<html lang="en" style="background-color: #2d383f;">
  <head>
    <meta charset="UTF-8">
    <title>Selecting Items</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="/background.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%;">Selecting Items</text>
          </svg>
        </div>
        <div class="tab-content-panel" data-tab-group="rhs">
          <div class="toggle-content is-visible tabcontent" id="controlsTab">
            <p>Shows how to use background items to explore dense networks.</p>
            <form autocomplete="off" onsubmit="return false" id="rhsForm">
              <div class="cicontent">
                <p>
                  Click on a node to focus on their out-bound connections.
                  You can customise the appearance of selected items with the menu below.
                </p>
              </div>
              <fieldset>
                <label class="control-label" for="appearance" style="margin-top:20px">Selection appearance:</label>
                <select class="input-block-level" id="appearance">
                  <option value="Default">Default</option>
                  <option value="Red">Red   </option>
                  <option value="Blue">Blue</option>
                </select>
              </fieldset>
            </form>
          </div>
        </div>
      </div>
    </div>
    <div id="moreParent">
      <div id="moreContainer">
      </div>
    </div>
    <div id="lazyScripts">
    </div>
  </body>
</html>
Loading source