Search

Arranging IT Networks

Combos

Use rectangular combos to visualise IT networks.

Arranging IT Networks
View live example →

In this demo, rectangular combos work alongside the sequential layout to deliver a clear overview of the network, its levels and connections.

Setting the adapt option to 'inCombo' preserves the sequential layout at the top chart level when the combo opens or closes.

Rectangular combos

Rectangular combos with grid arrangement are great for viewing large amounts of data at once. The items inside open combos are organised into a compact view that maximises the amount of instantly visible information.

Visualising connections

Using curved links in sequential layout can improve the readability of connections, especially for large charts with multiple connections between levels.

Combine them with features such as flow animation for additional highlight or to represent the flow in your data.

Another way to add detailed information is to use the chart.combo().reveal() function to keep underlying or important links visible. In this demo, the particularly suspicious computer and connection are both marked with a glyph and contrasting colour.

Key functions used:

import KeyLines from "keylines";
import { data } from "./data.js";

let chart;
let graph;

// Style info
const backgroundColour = "#1f1f1f";
const alertColour = "#e5309a";
const selectedColour = "white";
const linkColour = "#454545";
const topLevelLinkColour = "#39bffd";

// State tracking
let alwaysRevealedLinks = [];

// Find all the links that have alerts attached.
function getAlertLinks() {
  const alerts = [];
  chart.each({ type: "link" }, (link) => {
    if (link.d.alert) {
      alerts.push(link.id);
    }
  });
  return alerts;
}

function decorateAlertLinks(linkIds) {
  chart.setProperties(
    linkIds.map((id) => ({
      id,
      c: alertColour,
      g: [
        {
          c: alertColour,
          b: null,
          fi: { t: "fas fa-exclamation", c: "white" },
          e: 1.5,
        },
      ],
    })),
  );
}

function showTraffic(linkIds) {
  const toForeground = {};
  const newLinkProperties = linkIds.map((id) => {
    toForeground[id] = true;
    const link = chart.getItem(id);
    const c = link.d.alert ? alertColour : selectedColour;
    return {
      id,
      c,
      flow: link.d.flow,
    };
  });
  chart.setProperties(newLinkProperties);
  const reveal = alwaysRevealedLinks.concat(linkIds);
  chart.combo().reveal(reveal);
  chart.foreground((link) => toForeground[link.id], {
    type: "link",
    items: "underlying",
  });
}

function hideTraffic() {
  const revealedIds = chart.combo().reveal();
  chart.setProperties(
    revealedIds.map((id) => {
      const link = chart.getItem(id);
      return {
        id: link.id,
        c: link.d.alert ? alertColour : linkColour,
        flow: false,
      };
    }),
  );
  chart.combo().reveal(alwaysRevealedLinks);
}

function select(selections) {
  const itemId =
    selections.length > 0 ? selections[selections.length - 1] : null;
  const item = chart.getItem(itemId);
  if (item && item.type === "node" && !chart.combo().isCombo(itemId)) {
    showTraffic(graph.neighbours(itemId, { all: true }).links);
  } else {
    chart.foreground(() => true);
  }
}

async function onDoubleClick({ id, preventDefault, button }) {
  if (!id || button !== 0) {
    return;
  }

  const api = chart.combo();
  const combo = api.isCombo(id) ? id : chart.getItem(id).parentId;
  const opts = { adapt: "inCombo" };

  if (api.isCombo(combo)) {
    preventDefault();
    if (api.isOpen(combo)) {
      await api.close(combo, opts);
    } else {
      await api.open(combo, opts);
    }
    layout();
  }
}

function initialiseInteractions() {
  // perform layout on combo open/close
  chart.on("double-click", onDoubleClick);

  // reveal and foreground selected nodes and links
  chart.on("selection-change", () => {
    hideTraffic();
    select(chart.selection());
  });
}

// generate a list of all combos ordered by how deeply nested they are
function getComboList() {
  const comboIds = [];
  chart.each({ type: "node", items: "all" }, ({ id }) => {
    if (chart.combo().isCombo(id)) {
      comboIds.push(id);
    }
  });
  return comboIds;
}

function getInnerCombos() {
  const combo = chart.combo();
  return getComboList().filter((id) => {
    let isInnerCombo = true;
    // is not an inner combo if any child is a combo
    chart.each({ items: "all", type: "node" }, (item) => {
      if (item.parentId === id && combo.isCombo(item.id)) {
        isInnerCombo = false;
      }
    });
    return isInnerCombo;
  });
}

async function openAllCombos() {
  const allCombos = getComboList();
  const innerCombos = getInnerCombos();
  const outerCombos = allCombos.filter((id) => !innerCombos.includes(id));
  await chart.combo().open(allCombos, { animate: false });
  await chart.combo().arrange(outerCombos, {
    name: "grid",
    animate: false,
  });
  await chart.combo().arrange(innerCombos, {
    name: "grid",
    animate: false,
    tightness: 3,
  });
}

function colourTopLevelLinks() {
  chart.each({ type: "link", items: "toplevel" }, ({ id }) => {
    chart.setProperties({ id, c: topLevelLinkColour });
  });
}

async function startKeyLines() {
  const options = {
    backColour: backgroundColour,
    backgroundAlpha: 0.45,
    combos: {
      shape: "rectangle",
    },
    controlTheme: "dark",
    selectedLink: {},
    selectedNode: {
      b: selectedColour,
      bw: 3,
    },
    iconFontFamily: "Font Awesome 5 Free",
    handMode: true,
    defaultStyles: {
      comboGlyph: {
        p: 45,
      },
    },
    imageAlignment: {
      "fas fa-print": { e: 0.8 },
      "fas fa-laptop": { e: 0.75 },
      "fas fa-phone": { e: 0.8 },
      "fas fa-server": { e: 0.8 },
      "fas fa-sitemap": { e: 0.75, dy: -8 },
    },
  };

  chart = await KeyLines.create({ container: "klchart", options });

  initialiseInteractions();

  // Use a graph engine to track relations in the underlying data
  graph = KeyLines.getGraphEngine();
  graph.load(data);

  chart.load(data);

  // reveal the links with alerts attached and make sure they stay that way
  alwaysRevealedLinks = getAlertLinks();
  chart.combo().reveal(alwaysRevealedLinks);

  // also style them dramatically...
  decorateAlertLinks(alwaysRevealedLinks);
  await openAllCombos();
  colourTopLevelLinks();
  layout();
}

function layout() {
  chart.layout("sequential", { level: "level", linkShape: "curved" });
}

function loadFontsAndStart() {
  document.fonts.load('24px "Font Awesome 5 Free"').then(startKeyLines);
}

window.addEventListener("DOMContentLoaded", loadFontsAndStart);
import KeyLines from "keylines";
export const data = {
  items: [
    {
      type: "node",
      id: "223.112.181.149",
      t: [{ t: "Cambridge", position: "s" }, { t: "223.112.181.149" }],
      c: "grey",
      bw: 3,
      d: {
        type: "network",
        level: 1,
        location: "Cambridge",
      },
      fi: {
        t: "fas fa-sitemap",
        c: "white",
      },
      e: 2,
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
      oc: {
        c: "#292929",
        b: "#39bffd",
        t: "Cambridge\n223.112.181.149",
      },
    },
    {
      type: "node",
      id: "192.168.162.0",
      t: [{ t: "192.168.162.0" }],
      c: "grey",
      bw: 3,
      d: {
        type: "router",
        network: "223.112.181.149",
        ipPattern: "192.168.162.",
      },
      parentId: "223.112.181.149",
      e: 1.5,
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
      fi: {
        t: "fas fa-sitemap",
        c: "white",
      },
      oc: {
        bw: 3,
        c: "#333333",
        b: "#39bffd",
        t: "192.168.162.0",
      },
    },
    {
      id: "223.112.181.149-192.168.162.0",
      type: "link",
      id1: "223.112.181.149",
      id2: "192.168.162.0",
      w: 4,
      d: {
        port1: 80,
        port2: 443,
        flow: {
          velocity: 4.950921471449721,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "192.168.248.0",
      t: [{ t: "192.168.248.0" }],
      c: "grey",
      bw: 3,
      d: {
        type: "router",
        network: "223.112.181.149",
        ipPattern: "192.168.248.",
      },
      parentId: "223.112.181.149",
      e: 1.5,
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
      fi: {
        t: "fas fa-sitemap",
        c: "white",
      },
      oc: {
        bw: 3,
        c: "#333333",
        b: "#39bffd",
        t: "192.168.248.0",
      },
    },
    {
      id: "223.112.181.149-192.168.248.0",
      type: "link",
      id1: "223.112.181.149",
      id2: "192.168.248.0",
      w: 4,
      d: {
        port1: 8080,
        port2: 443,
        flow: {
          velocity: 2.356821830746494,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.162.126",
      t: [
        {
          fi: {
            t: "fas fa-laptop",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.162.126",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "linux",
        network: "223.112.181.149",
        subnet: "192.168.162.0",
      },
      parentId: "192.168.162.0",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      id: "192.168.162.0-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "192.168.162.0",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 20,
        port2: 443,
        flow: {
          velocity: 3.966807830948753,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.248.236",
      t: [
        {
          fi: {
            t: "fas fa-laptop",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.248.236",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "linux",
        network: "223.112.181.149",
        subnet: "192.168.248.0",
      },
      parentId: "192.168.248.0",
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      id: "192.168.248.0-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "192.168.248.0",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 20,
        port2: 80,
        flow: {
          velocity: 2.0052035235238552,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.162.242",
      t: [
        {
          fi: {
            t: "fas fa-phone",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.162.242",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "phone",
        network: "223.112.181.149",
        subnet: "192.168.162.0",
      },
      parentId: "192.168.162.0",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      id: "192.168.162.0-223.112.181.149::192.168.162.242",
      type: "link",
      id1: "192.168.162.0",
      id2: "223.112.181.149::192.168.162.242",
      w: 4,
      d: {
        port1: 443,
        port2: 80,
        flow: {
          velocity: 9.51712284042533,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.162.137",
      t: [
        {
          fi: {
            t: "fas fa-laptop",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.162.137",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "linux",
        network: "223.112.181.149",
        subnet: "192.168.162.0",
      },
      parentId: "192.168.162.0",
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.162.118",
      t: [
        {
          fi: {
            t: "fas fa-laptop",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.162.118",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "linux",
        network: "223.112.181.149",
        subnet: "192.168.162.0",
      },
      parentId: "192.168.162.0",
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      id: "192.168.162.0-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "192.168.162.0",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 20,
        port2: 8080,
        flow: {
          velocity: 0.03162958284387729,
        },
      },
      c: "#454545",
    },
    {
      id: "192.168.162.0-223.112.181.149::192.168.162.137",
      type: "link",
      id1: "192.168.162.0",
      id2: "223.112.181.149::192.168.162.137",
      w: 4,
      d: {
        port1: 8080,
        port2: 20,
        flow: {
          velocity: 1.1161726836188146,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.248.192",
      t: [
        {
          fi: {
            t: "fas fa-laptop",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.248.192",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "win",
        network: "223.112.181.149",
        subnet: "192.168.248.0",
      },
      parentId: "192.168.248.0",
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      id: "192.168.248.0-223.112.181.149::192.168.248.192",
      type: "link",
      id1: "192.168.248.0",
      id2: "223.112.181.149::192.168.248.192",
      w: 4,
      d: {
        port1: 8080,
        port2: 8080,
        flow: {
          velocity: 8.30920446549413,
        },
      },
      c: "#454545",
    },
    {
      type: "node",
      id: "223.112.181.149::192.168.248.155",
      t: [
        {
          fi: {
            t: "fas fa-laptop",
          },
          fs: 60,
          position: {
            vertical: "top",
          },
          padding: {
            top: 5,
          },
        },
        {
          t: "192.168.248.155",
          position: {
            vertical: "bottom",
          },
          fs: 15,
          padding: {
            bottom: 4,
          },
        },
      ],
      c: "grey",
      w: 130,
      h: 70,
      d: {
        type: "linux",
        network: "223.112.181.149",
        subnet: "192.168.248.0",
      },
      parentId: "192.168.248.0",
      sh: "box",
      fbc: "rgba(0,0,0,0)",
      fc: "white",
    },
    {
      id: "192.168.248.0-223.112.181.149::192.168.248.155",
      type: "link",
      id1: "192.168.248.0",
      id2: "223.112.181.149::192.168.248.155",
      w: 4,
      d: {
        port1: 443,
        port2: 22,
        flow: {
          velocity: 6.664337520331777,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.126-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.162.126",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 22,
        port2: 8080,
        flow: {
          velocity: 2.0425414548962095,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.126-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.162.126",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 20,
        port2: 20,
        flow: {
          velocity: 4.691027944372806,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.126-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "223.112.181.149::192.168.162.126",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 20,
        port2: 8080,
        flow: {
          velocity: 6.90387391871047,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.126-223.112.181.149::192.168.162.242",
      type: "link",
      id1: "223.112.181.149::192.168.162.126",
      id2: "223.112.181.149::192.168.162.242",
      w: 4,
      d: {
        port1: 80,
        port2: 22,
        flow: {
          velocity: 7.060971955773012,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.126-223.112.181.149::192.168.248.155",
      type: "link",
      id1: "223.112.181.149::192.168.162.126",
      id2: "223.112.181.149::192.168.248.155",
      w: 4,
      d: {
        port1: 20,
        port2: 22,
        flow: {
          velocity: 9.723244415824547,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.248.192",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.248.192",
      w: 4,
      d: {
        port1: 443,
        port2: 8080,
        flow: {
          velocity: 0.9449581426781406,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.248.155",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.248.155",
      w: 4,
      d: {
        port1: 8080,
        port2: 80,
        flow: {
          velocity: 7.042428747932439,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 8080,
        port2: 20,
        flow: {
          velocity: 3.7032959392292075,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 443,
        port2: 20,
        flow: {
          velocity: 4.116079461387418,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.248.192",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.248.192",
      w: 4,
      d: {
        port1: 80,
        port2: 22,
        flow: {
          velocity: 8.67323757284284,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 22,
        port2: 8080,
        flow: {
          velocity: 5.9946802689124645,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.236-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "223.112.181.149::192.168.248.236",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 443,
        port2: 443,
        flow: {
          velocity: 9.997017366850457,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.242-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.162.242",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 80,
        port2: 22,
        flow: {
          velocity: 8.888415939650695,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.242-223.112.181.149::192.168.248.192",
      type: "link",
      id1: "223.112.181.149::192.168.162.242",
      id2: "223.112.181.149::192.168.248.192",
      w: 4,
      d: {
        port1: 20,
        port2: 8080,
        flow: {
          velocity: 3.6163660426700694,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.242-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.162.242",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 20,
        port2: 22,
        flow: {
          velocity: 9.280001759770045,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.242-223.112.181.149::192.168.162.137",
      type: "link",
      id1: "223.112.181.149::192.168.162.242",
      id2: "223.112.181.149::192.168.162.137",
      w: 4,
      d: {
        port1: 22,
        port2: 22,
        flow: {
          velocity: 1.4941183350521925,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.118-223.112.181.149::192.168.162.242",
      type: "link",
      id1: "223.112.181.149::192.168.162.118",
      id2: "223.112.181.149::192.168.162.242",
      w: 4,
      d: {
        port1: 20,
        port2: 20,
        flow: {
          velocity: 4.046308247421475,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.118-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "223.112.181.149::192.168.162.118",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 20,
        port2: 443,
        flow: {
          velocity: 6.795889630088077,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.118-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.162.118",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 8080,
        port2: 443,
        flow: {
          velocity: 0.6245614644998576,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.248.155",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.248.155",
      w: 4,
      d: {
        port1: 80,
        port2: 80,
        flow: {
          velocity: 9.353581551521204,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 80,
        port2: 20,
        flow: {
          velocity: 9.31322157785755,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 443,
        port2: 443,
        flow: {
          velocity: 4.131968468890945,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 443,
        port2: 20,
        flow: {
          velocity: 8.147784657086078,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 443,
        port2: 20,
        flow: {
          velocity: 6.394807610242763,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.162.137",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.162.137",
      w: 4,
      d: {
        port1: 443,
        port2: 22,
        flow: {
          velocity: 5.97366969615851,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 8080,
        port2: 443,
        flow: {
          velocity: 0.5260086750719006,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.162.137-223.112.181.149::192.168.162.242",
      type: "link",
      id1: "223.112.181.149::192.168.162.137",
      id2: "223.112.181.149::192.168.162.242",
      w: 4,
      d: {
        port1: 22,
        port2: 22,
        flow: {
          velocity: 4.855363791923056,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.192-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "223.112.181.149::192.168.248.192",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 8080,
        port2: 8080,
        flow: {
          velocity: 8.450919070188087,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.192-223.112.181.149::192.168.162.137",
      type: "link",
      id1: "223.112.181.149::192.168.248.192",
      id2: "223.112.181.149::192.168.162.137",
      w: 4,
      d: {
        port1: 80,
        port2: 8080,
        flow: {
          velocity: 4.573762733480549,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.155-223.112.181.149::192.168.162.137",
      type: "link",
      id1: "223.112.181.149::192.168.248.155",
      id2: "223.112.181.149::192.168.162.137",
      w: 4,
      d: {
        port1: 22,
        port2: 8080,
        flow: {
          velocity: 9.373201700983657,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.155-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.248.155",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 443,
        port2: 8080,
        flow: {
          velocity: 4.88708157709882,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.155-223.112.181.149::192.168.162.126",
      type: "link",
      id1: "223.112.181.149::192.168.248.155",
      id2: "223.112.181.149::192.168.162.126",
      w: 4,
      d: {
        port1: 80,
        port2: 443,
        flow: {
          velocity: 6.654234954636449,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.155-223.112.181.149::192.168.162.118",
      type: "link",
      id1: "223.112.181.149::192.168.248.155",
      id2: "223.112.181.149::192.168.162.118",
      w: 4,
      d: {
        port1: 443,
        port2: 443,
        flow: {
          velocity: 1.4787139498451385,
        },
      },
      c: "#454545",
    },
    {
      id: "223.112.181.149::192.168.248.155-223.112.181.149::192.168.248.236",
      type: "link",
      id1: "223.112.181.149::192.168.248.155",
      id2: "223.112.181.149::192.168.248.236",
      w: 4,
      d: {
        port1: 22,
        port2: 443,
        flow: {

// ...truncated 4334 lines
<!doctype html>
<html lang="en" style="background-color: #2d383f">
  <head>
    <meta charset="utf-8" />
    <title>Arranging IT Networks</title>
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
    <link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
    <link
      rel="stylesheet"
      type="text/css"
      href="@fortawesome/[email protected]/css/fontawesome.css"
    />
    <link
      rel="stylesheet"
      type="text/css"
      href="@fortawesome/[email protected]/css/solid.css"
    />
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <div id="klchart" class="klchart"></div>
    <script type="module" src="./code.js"></script>
  </body>
</html>
.klchart {
  border: none;
  background-color: #1f1f1f;
}

Terms of use

These terms do not alter or supersede any existing agreements between you (or your employer) and us.

By accessing or using any Content you agree to be bound by these Terms of Use. Please review these terms carefully before using the website.

The contents of this website, including but not limited to any text, code samples, API references, schemas, interactive tools, and other materials (collectively, the 'Content'), are made available for informational and internal evaluation purposes only. All intellectual property rights in the Content are reserved. No licence is granted to use the Content for any commercial purpose, or to copy, distribute, modify, reverse-engineer, or incorporate any part of the Content into any product or service, without our prior written consent.

This Content is provided “as is” and “as available,” without any representations, warranties, or guarantees of any kind, whether express or implied, including but not limited to implied warranties of merchantability, fitness for a particular purpose, non-infringement, or accuracy. To the fullest extent permitted by applicable law, we expressly exclude and disclaim all implied warranties, conditions, and other terms that might otherwise be implied.

We disclaim all liability for any loss or damage, whether direct, indirect, incidental, consequential, or otherwise, arising from any reliance placed on the Content or from your use of it, to the fullest extent permitted by applicable law. By continuing to access or use the Content, you acknowledge and agree to these terms.