//
//     Copyright © 2011-2025 Cambridge Intelligence Limited.
//     All rights reserved.
//
//     Sample Code
//
//!    Explore ways to style links and make them stand out.
import KeyLines from "keylines";
import { data } from "./linkstyles-data.js";

let chart;
let doAnts = false;

// Alter the view by zooming to the 'fit' position
function fitZoom(animate) {
  chart.zoom("fit", { animate, time: 500 });
}

// Format the properties of the displayed item (may accept a nav control id)
function prettyPrint() {
  const id = chart.selection()[0];
  const item = chart.getItem(id);
  if (item) {
    // Avoid printing the coordinates of the elements in the display window
    delete item.x;
    delete item.y;
    document.getElementById("display").innerHTML = JSON.stringify(
      item,
      null,
      1
    );
  } else if (!id) {
    // If the background was clicked, clear the selection
    document.getElementById("display").innerHTML = "No item selected";
  }
}

function toggleAnts() {
  doAnts = !doAnts;
  // Update the flow property of the nodes having an id
  // that starts with 'flow'.
  chart.each({ type: "link" }, (link) => {
    if (link.d && link.d.flow) {
      chart.setProperties({
        id: link.id,
        flow: doAnts ? { velocity: link.d.flow } : undefined,
      });
    }
  });

  // Update the source code displayed to reflect the flow changes.
  prettyPrint();
}

function initializeInteractions() {
  // When clicking on an item, show its properties on the right-hand side
  chart.on("selection-change", prettyPrint);

  // Zoom the view to its original position when double-clicking the background
  chart.on("double-click", ({ id, preventDefault }) => {
    if (!chart.getItem(id)) {
      fitZoom(true);
    }
    // Default behaviour is to zoom in - we preventDefault to override this
    preventDefault();
  });

  // prevent nodes from being dragged
  chart.on("drag-start", ({ setDragOptions, type }) => {
    if (type === "node") {
      setDragOptions({ type: chart.options().handMode ? "pan" : "marquee" });
    }
  });

  const inlineElement = document.getElementById("inlineEnabled");
  document.getElementById("flowEnabled").addEventListener("change", toggleAnts);
  inlineElement.addEventListener("change", () => {
    chart.options({
      linkStyle: {
        inline: !!inlineElement.checked,
      },
    });
  });
}

async function loadKeylines() {
  const options = {
    logo: { u: "/images/Logo.png" },
    selectionColour: "#FF9933",
    selfLinks: true,
    overview: { icon: false },
    handMode: true,
  };

  chart = await KeyLines.create({ container: "klchart", options });
  chart.load(data); // load the chart data
  fitZoom(); // adjust the view to 'fit' the displayed chart

  initializeInteractions(); // Attach the chart and user events
}

window.addEventListener("DOMContentLoaded", loadKeylines);
<!DOCTYPE html>
<html lang="en" style="background-color: #2d383f;">
  <head>
    <meta charset="UTF-8">
    <title>Style Links</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="/linkstyles.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%;">Style Links</text>
          </svg>
        </div>
        <div class="tab-content-panel" data-tab-group="rhs">
          <div class="toggle-content is-visible tabcontent" id="controlsTab">
            <p>Select an item to view its source.</p>
            <form autocomplete="off" onsubmit="return false" id="rhsForm">
              <div class="cicontent">
                <div class="settings">
                  <label class="checkbox" style="margin-bottom:16px;margin-top:16px;">
                    <input id="flowEnabled" type="checkbox"><span>&nbsp;Enable Flow</span>
                  </label>
                  <label class="checkbox" style="margin-bottom:16px;">
                    <input id="inlineEnabled" type="checkbox"><span>&nbsp;Inline Labels    </span>
                  </label>
                  <pre id="display" style="-webkit-user-select: text; -khtml-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; word-break: keep-all;">No item selected</pre>
                </div>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
    <div id="moreParent">
      <div id="moreContainer">
      </div>
    </div>
    <div id="lazyScripts">
    </div>
  </body>
</html>
Loading source