This demo is a version of Time Periods demo and uses Vue version 3.
This demo shows how to use the KeyLines Vue component to:
- Declare multiple components
- Add font icons and tooltips
- Set options on the chart
- Listen for the change events on time bar and capture them on the controller to filter the chart
Vue Component
We've written the source code and chart component in ES6. We've also bundled the demo, chart component and Vue.js into a single file using Webpack, and transpiled the code to JavaScript using Babel.
See also
Tutorial: Vue Tutorial
KeyLines Vue component: Vue Reference
Vue official page: vuejs.org
Key functions used:
import { createApp } from "vue";
import Demo from "./App.vue";
createApp(Demo).mount("#kl-container"); <template>
<div class="chart-wrapper demo-cols">
<left-panel name="vuechartfilter">
<span
id="tooltip"
:class="tooltip.tooltipClass"
:style="{ left: tooltip.left, top: tooltip.top }"
>
<div :class="tooltip.arrowClass"></div>
<tr>
<td class="table-cell"><b>Appointed on: </b></td>
<td>{{ tooltip.start }}</td>
</tr>
<tr>
<td class="table-cell"><b>Resigned on: </b></td>
<td>{{ tooltip.end }}</td>
</tr>
</span>
<kl-chart
id="kl"
containerClass="klchart klchart-timebar"
:animateOnLoad="true"
:data="data"
:options="chartOptions"
@kl-ready="onChartReady"
@kl-selection-change="highlightSelections"
@kl-hover="toggleTooltip"
@kl-drag-move="toggleTooltip"
/>
<kl-timebar
id="timebar"
containerClass="kltimebar"
:animateOnLoad="true"
:data="data"
:options="timebarOptions"
@kl-change="onTimebarChange"
@kl-ready="onTimebarReady"
/>
</left-panel>
<right-panel
title="Vue.js Integration"
name="vuechartfilter"
description="Use Vue and the time bar to filter chart items."
>
<fieldset>
<legend>Interaction</legend>
<ul>
<li>Use the time bar controls to see changes over time</li>
<li>Hover/click a link to to show the duration of an individual's directorship</li>
<li>Multi-select up to three items to highlight their neighbours</li>
</ul>
</fieldset>
<fieldset>
<legend>Data Format</legend>
<p>
The time bar and chart data formats are similar, so you can pass the same data object to
both components.
</p>
</fieldset>
</right-panel>
</div>
</template>
<script>
import KlChart from "./Chart.vue";
import KlTimebar from "./Timebar.vue";
import LeftPanel from "./LeftPanel.vue";
import RightPanel from "./RightPanel.vue";
import data from "./data";
export default {
name: "demo",
components: {
LeftPanel,
RightPanel,
KlChart,
KlTimebar,
},
data: () => ({
chartOptions: {
logo: { u: "/images/Logo.png" },
handMode: true,
iconFontFamily: "Font Awesome 5 Free",
selectionColour: "#35495E",
hover: 0,
selectedNode: {
fbc: "rgba(0,0,0,0)",
},
selectedLink: {
fbc: "rgba(0,0,0,0)",
},
},
timebarOptions: {
histogram: {
colour: "#42B883",
highlightColour: "#35495E",
markColour: "rgb(192, 192, 192)",
markHiColour: "rgb(105, 105, 105)",
},
playSpeed: 30,
},
greyColours: ["rgb(105, 105, 105)", "rgb(192, 192, 192)"],
// only style the first 3 selections
selectionColours: [
["#9600d5", "#d0a3cb"],
["#0044ff", "#6b93ff"],
["#ff0000", "#ff9e9e"],
],
marks: [
{
dt1: new Date("01 Jan 2018 01:00:00"),
dt2: new Date("01 Jan 2050 01:00:00"),
},
],
data,
tooltip: {
start: "",
end: "",
left: "",
top: "",
tooltipClass: "hidden",
arrowClass: "arrow",
},
}),
mounted() {
(document.fonts.load('24px "Font Awesome 5 Free"'),
// set font icons for each node type
this.data.items.forEach((item) => {
if (item && item.type === "node") {
item.fi = {
c: this.greyColours[0],
t: item.d.type === "person" ? "fas fa-user" : "fas fa-building",
};
}
}));
},
methods: {
onChartReady(chart) {
this.chart = chart;
},
onTimebarReady(timebar) {
this.timebar = timebar;
this.timebar.mark(this.marks);
},
onTimebarChange() {
if (this.chart && this.timebar) {
// filter the chart to show only items in the new range
this.chart.filter(this.timebar.inRange, { animate: false, type: "link" }).then(() => {
this.chart.layout("organic", { time: 500, mode: "adaptive", easing: "linear" });
});
}
},
buildItemStyling(item, width, colour, border = false) {
if (item.type === "node") {
return {
id: item.id,
fi: {
c: colour,
t: item.d.type === "person" ? "fas fa-user" : "fas fa-building",
},
b: border ? colour : null,
};
}
// else it's a link
return { id: item.id, w: width || 4, c: colour };
},
highlightSelections() {
if (!this.chart || !this.timebar) return;
const timebarSelection = [];
const chartProperties = {};
// set default colouring
this.chart.each({ type: "all" }, (item) => {
chartProperties[item.id] = this.buildItemStyling(
item,
3,
item.type === "node" ? this.greyColours[0] : this.greyColours[1]
);
});
let selectedIds = this.chart.selection();
if (selectedIds) {
if (selectedIds.length > this.selectionColours.length) {
selectedIds = selectedIds.slice(0, this.selectionColours.length);
this.chart.selection(selectedIds);
}
selectedIds.forEach((id, index) => {
let neighbouringNodes = [];
let links = [];
const item = this.chart?.getItem(id);
const colour =
index < this.selectionColours.length
? this.selectionColours[index][0]
: this.greyColours[1];
const linkColour = this.selectionColours[index][1];
if (item && item.type === "node") {
// all: true - applies styles to hidden nodes + links not in current time range
const neighbours = this.chart?.graph().neighbours(id, { all: true });
if (neighbours && neighbours.links) {
links = neighbours.links;
neighbouringNodes = neighbours.nodes;
}
// colour node
chartProperties[id] = this.buildItemStyling(item, 3, colour, true);
links.forEach((link) => {
const linkItem = this.chart?.getItem(link);
chartProperties[link] = this.buildItemStyling(linkItem, 5, linkColour);
});
} else if (item && item.type === "link") {
links.push(id);
neighbouringNodes.push(item.id1, item.id2);
// colour link
chartProperties[id] = this.buildItemStyling(item, 5, colour);
}
// colour neighbour nodes
neighbouringNodes.forEach((neighbourId) => {
if (
chartProperties[neighbourId].fi.c === this.greyColours[0] &&
index < this.selectionColours.length
) {
chartProperties[neighbourId] = this.buildItemStyling(
this.chart?.getItem(neighbourId),
3,
this.selectionColours[index][1]
);
}
});
// and select in the timebar
timebarSelection.push({
id: links,
index,
c: colour,
});
});
this.timebar.selection(timebarSelection);
this.chart.setProperties(Object.keys(chartProperties).map((key) => chartProperties[key]));
}
},
getDateFromTimestamp(timestamp) {
return timestamp ? new Date(timestamp).toDateString().slice(4) : "n/a";
},
toggleTooltip({ id, x, y }) {
if (this.chart) {
const item = id ? this.chart.getItem(id) : null;
const viewWidth = this.chart.viewOptions().width;
if (item && item.type === "link") {
const timebarItem = data.items.filter((tbItem) => {
if (tbItem.id === item.id) {
return tbItem;
}
});
this.tooltip.start = this.getDateFromTimestamp(timebarItem[0].dt[0].dt1);
this.tooltip.end = this.getDateFromTimestamp(timebarItem[0].dt[0].dt2);
// style tooltip to left of cursor if it's x position + width exceeds
// the remaining chart space.
if (viewWidth && viewWidth > x + 250) {
this.tooltip.top = `${y - 24}px`;
this.tooltip.left = `${x + 22}px`;
this.tooltip.tooltipClass = "";
} else {
this.tooltip.top = `${y - 24}px`;
this.tooltip.left = `${x - 218}px`;
this.tooltip.tooltipClass = "right";
}
} else {
this.tooltip.tooltipClass = "hidden";
}
}
},
},
};
</script> <script>
import KlComponent from "./Keylines.vue";
export default {
name: "KlChart",
extends: KlComponent,
data: () => ({
type: "chart",
}),
methods: {
onLoad(options) {
return this.component.layout("organic", options);
},
},
};
</script> <script>
import KlComponent from "./Keylines.vue";
export default {
name: "KlTimebar",
extends: KlComponent,
data: () => ({
type: "timebar",
}),
methods: {
onLoad() {
return this.component.zoom("fit");
},
},
};
</script> <script>
const leftPanelTemplate = `
<div class="flex1" id="lhs">
<div id="lhsVisual" style="height: 99%;" class="toggle-content is-visible">
<slot></slot>
</div>
<div id="lhsSource" class="toggle-content"/>
</div>
`;
export default {
name: "LeftPanel",
props: {
name: String,
},
mounted() {
const sourceCodeElement = document.getElementById("lhsSource");
const sourceCode = `<iframe id="sourceView" style="width: 100%; height: 100%; border: none;" src="source-${this.name}.js.htm" scrolling="no"></iframe>`;
sourceCodeElement.innerHTML = sourceCode;
},
template: leftPanelTemplate,
};
</script> <script>
const rightPanelTemplate = `
<div class="rhs citext flex flex-column">
<div class="title-bar">
<h3 class="flex1">${document.title.split("|")[0]}</h3>
<div class="buttons flex" id="titlebarbuttons">
<a class="btn btn-label disabled fshide" href="#" data-toggle="tooltip" id="fullscreenDisabled">
<i class="fa fa-compress"></i>
</a>
<a class="btn btn-label" href="#" data-toggle="tooltip" id="fullscreenButton">
<i class="fa fa-expand"></i>
</a>
</div>
</div>
<div class="tabsdiv tab" data-tab-group="rhs">
<a class="btn btn-spaced fshide rhs-toggle fancy-button" id="closeRHS" href="#" data-toggle="tooltip">
<i class="fa fa-chevron-right"></i>
</a>
<button class="tablinks active" name="controlsTab" type="button">Controls</button>
<button class="tablinks" name="aboutTab" type="button">About</button>
<button class="tablinks" name="sourceTab" type="button">Source</button>
</div>
<div class="tab-content-panel flex1" data-tab-group="rhs">
<div class="toggle-content is-visible tabcontent" id="controlsTab">
<div class="cicontent">
<img class="kl-center vue-logo" :src="image.src" :alt="image.alt" />
<slot></slot>
</div>
</div>
<div ref="aboutTab" class="toggle-content tabcontent" id="aboutTab"></div>
<div ref="sourceTab" class="toggle-content tabcontent" id="sourceTab"></div>
</div>
</div>
`;
export default {
name: "RightPanel",
props: {
title: String,
name: String,
description: String,
isFullscreenAvailable: {
type: Boolean,
default: () => typeof doFullScreen === "function",
},
},
mounted() {
const sourcePanel = document.getElementById("sourcePanel");
const aboutPanel = document.getElementById("aboutPanel");
if (sourcePanel && aboutPanel) {
// re-assign parent of child elements, rather than copy HTML so as to not remove any event handlers
this.$refs.sourceTab.appendChild(sourcePanel);
for (const child of Array.from(sourcePanel.children)) {
this.$refs.sourceTab.appendChild(child);
}
const aboutTemplate = aboutPanel.innerHTML;
this.$refs.aboutTab.innerHTML = aboutTemplate;
}
},
computed: {
image() {
return {
src: `images/${this.name}/vuejs.png`,
alt: "Vue.js logo",
};
},
},
template: rightPanelTemplate,
};
</script> */ Cambridge Intelligence Limited. // All rights reserved. //
<template>
<div ref="container" :class="containerClass" :style="styleObject"></div>
</template>
<script>
import KeyLines from "keylines";
export default {
name: "KlComponent",
props: {
id: {
type: String,
required: true,
},
container: Object,
containerClass: String,
styleObject: Object,
options: Object,
data: Object,
animateOnLoad: {
type: Boolean,
default: false,
},
selection: {
type: Array,
default: () => [],
},
},
mounted() {
KeyLines.create({
id: this.id,
options: this.options,
container: this.$refs ? this.$refs.container : null,
type: this.type,
})
.then((component) => {
this.klcreate(component);
})
.catch(console.err);
},
beforeUnmount() {
if (this.component) {
this.component.destroy();
}
},
methods: {
onEvent(props) {
const name = "kl-" + props.name;
this.$emit("kl-all", props);
this.$emit(name, props.event);
},
klcreate(component) {
this.component = component;
this.component.on("all", this.onEvent);
this.component
.load(this.data)
.then(() => this.onLoad({ animate: !!this.animateOnLoad }))
.then(() => {
component.selection(this.selection);
this.$emit("kl-ready", component);
});
},
},
};
</script> export default {
type: "LinkChart",
items: [
{
type: "node",
id: "Brooke Fields",
t: "Brooke Fields",
d: {
type: "person",
},
},
{
type: "node",
id: "Gina Carlson",
t: "Gina Carlson",
d: {
type: "person",
},
},
{
type: "node",
id: "Guillermo Vaughn",
t: "Guillermo Vaughn",
d: {
type: "person",
},
},
{
type: "node",
id: "Rose Ingram",
t: "Rose Ingram",
d: {
type: "person",
},
},
{
type: "node",
id: "Jeannie Wolfe",
t: "Jeannie Wolfe",
d: {
type: "person",
},
},
{
type: "node",
id: "Dave Rice",
t: "Dave Rice",
d: {
type: "person",
},
},
{
type: "node",
id: "Paul Watts",
t: "Paul Watts",
d: {
type: "person",
},
},
{
type: "node",
id: "Danny Matthews",
t: "Danny Matthews",
d: {
type: "person",
},
},
{
type: "node",
id: "Anthony Mitchell",
t: "Anthony Mitchell",
d: {
type: "person",
},
},
{
type: "node",
id: "Alfred Hicks",
t: "Alfred Hicks",
d: {
type: "person",
},
},
{
type: "node",
id: "Adrian Mcdaniel",
t: "Adrian Mcdaniel",
d: {
type: "person",
},
},
{
type: "node",
id: "Kerry Waters",
t: "Kerry Waters",
d: {
type: "person",
},
},
{
type: "node",
id: "Felix Floyd",
t: "Felix Floyd",
d: {
type: "person",
},
},
{
type: "node",
id: "Noel Luna",
t: "Noel Luna",
d: {
type: "person",
},
},
{
type: "node",
id: "Tami Lindsey",
t: "Tami Lindsey",
d: {
type: "person",
},
},
{
type: "node",
id: "Damon Douglas",
t: "Damon Douglas",
d: {
type: "person",
},
},
{
type: "node",
id: "Diana Greene",
t: "Diana Greene",
d: {
type: "person",
},
},
{
type: "node",
id: "Gary King",
t: "Gary King",
d: {
type: "person",
},
},
{
type: "node",
id: "Phantom Corporation",
t: "Phantom Corporation",
d: {
type: "company",
},
},
{
type: "node",
id: "Melon Arts",
t: "Melon Arts",
d: {
type: "company",
},
},
{
type: "node",
id: "Green",
t: "Green",
d: {
type: "company",
},
},
{
type: "node",
id: "Marblightning",
t: "Marblightning",
d: {
type: "company",
},
},
{
type: "node",
id: "Cycloration",
t: "Cycloration",
d: {
type: "company",
},
},
{
type: "node",
id: "Bluetronics",
t: "Bluetronics",
d: {
type: "company",
},
},
{
type: "node",
id: "Summitechnologies",
t: "Summitechnologies",
d: {
type: "company",
},
},
{
type: "node",
id: "Cloudwalk",
t: "Cloudwalk",
d: {
type: "company",
},
},
{
type: "node",
id: "Jettechs",
t: "Jettechs",
d: {
type: "company",
},
},
{
type: "node",
id: "Quadbridge",
t: "Quadbridge",
d: {
type: "company",
},
},
{
type: "node",
id: "Crow Navigations",
t: "Crow Navigations",
d: {
type: "company",
},
},
{
type: "node",
id: "Grasshopper Co.",
t: "Grasshopper Co.",
d: {
type: "company",
},
},
{
type: "node",
id: "Daydream Security",
t: "Daydream Security",
d: {
type: "company",
},
},
{
type: "node",
id: "Joytechs",
t: "Joytechs",
d: {
type: "company",
},
},
{
type: "node",
id: "Dwarfoods",
t: "Dwarfoods",
d: {
type: "company",
},
},
{
type: "node",
id: "Cliffoods",
t: "Cliffoods",
d: {
type: "company",
},
},
{
type: "node",
id: "Vinedustries",
t: "Vinedustries",
d: {
type: "company",
},
},
{
type: "node",
id: "Bansheewares",
t: "Bansheewares",
d: {
type: "company",
},
},
{
type: "node",
id: "Moonshine",
t: "Moonshine",
d: {
type: "company",
},
},
{
type: "node",
id: "Mapleway",
t: "Mapleway",
d: {
type: "company",
},
},
{
type: "node",
id: "Diamond Aviation",
t: "Diamond Aviation",
d: {
type: "company",
},
},
{
type: "node",
id: "Grotto Corp",
t: "Grotto Corp",
d: {
type: "company",
},
},
{
type: "node",
id: "Root Aviation",
t: "Root Aviation",
d: {
type: "company",
},
},
{
type: "node",
id: "White Wolfoods",
t: "White Wolfoods",
d: {
type: "company",
},
},
{
type: "node",
id: "Greenetworks",
t: "Greenetworks",
d: {
type: "company",
},
},
{
type: "node",
id: "Honeytelligence",
t: "Honeytelligence",
d: {
type: "company",
},
},
{
type: "node",
id: "Tempestechnologies",
t: "Tempestechnologies",
d: {
type: "company",
},
},
{
type: "node",
id: "Phoenixland",
t: "Phoenixland",
d: {
type: "company",
},
},
{
type: "node",
id: "Crystalsun",
t: "Crystalsun",
d: {
type: "company",
},
},
{
type: "link",
id: "Brooke Fields-Phantom Corporation",
id1: "Brooke Fields",
id2: "Phantom Corporation",
dt: [
{
dt1: 1339014193119,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Melon Arts",
id1: "Brooke Fields",
id2: "Melon Arts",
dt: [
{
dt1: 1247271160185,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Green",
id1: "Brooke Fields",
id2: "Green",
dt: [
{
dt1: 1237397195464,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Marblightning",
id1: "Brooke Fields",
id2: "Marblightning",
dt: [
{
dt1: 1268721087691,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Cycloration",
id1: "Brooke Fields",
id2: "Cycloration",
dt: [
{
dt1: 1310952185992,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Bluetronics",
id1: "Gina Carlson",
id2: "Bluetronics",
dt: [
{
dt1: 1191238914316,
dt2: 1270569157085,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Summitechnologies",
id1: "Gina Carlson",
id2: "Summitechnologies",
dt: [
{
dt1: 1276109390365,
dt2: 1348661017536,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Cloudwalk",
id1: "Gina Carlson",
id2: "Cloudwalk",
dt: [
{
dt1: 1348270245074,
dt2: 1412908707443,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Jettechs",
id1: "Gina Carlson",
id2: "Jettechs",
dt: [
{
dt1: 1415551838802,
dt2: 1465786744438,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Quadbridge",
id1: "Gina Carlson",
id2: "Quadbridge",
dt: [
{
dt1: 1459806246849,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Guillermo Vaughn-Crow Navigations",
id1: "Guillermo Vaughn",
id2: "Crow Navigations",
dt: [
{
dt1: 1418792877334,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Rose Ingram-Grasshopper Co.",
id1: "Rose Ingram",
id2: "Grasshopper Co.",
dt: [
{
dt1: 1383109469104,
dt2: 1498149360662,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Rose Ingram-Daydream Security",
id1: "Rose Ingram",
id2: "Daydream Security",
dt: [
{
dt1: 1236890263269,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Jeannie Wolfe-Joytechs",
id1: "Jeannie Wolfe",
id2: "Joytechs",
dt: [
{
dt1: 1266649394407,
dt2: 1418563289105,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Dave Rice-Dwarfoods",
id1: "Dave Rice",
id2: "Dwarfoods",
dt: [
{
dt1: 1435235563645,
dt2: 1439593633782,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Paul Watts-Cliffoods",
id1: "Paul Watts",
id2: "Cliffoods",
dt: [
{
dt1: 1348460379175,
dt2: 1430497186231,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Paul Watts-Vinedustries",
id1: "Paul Watts",
id2: "Vinedustries",
dt: [
{
dt1: 1342980716145,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Danny Matthews-Bansheewares",
id1: "Danny Matthews",
id2: "Bansheewares",
dt: [
{
dt1: 1212592504689,
dt2: 1506411552619,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Anthony Mitchell-Moonshine",
id1: "Anthony Mitchell",
id2: "Moonshine",
dt: [
{
dt1: 1294680086436,
dt2: 1513775556429,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Anthony Mitchell-Mapleway",
id1: "Anthony Mitchell",
id2: "Mapleway",
dt: [
{
dt1: 1404224388156,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Alfred Hicks-Diamond Aviation",
id1: "Alfred Hicks",
id2: "Diamond Aviation",
dt: [
{
dt1: 1302567304700,
dt2: 1435579135260,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Adrian Mcdaniel-Grotto Corp",
id1: "Adrian Mcdaniel",
id2: "Grotto Corp",
dt: [
{
dt1: 1275605687635,
dt2: 1302441510735,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Kerry Waters-Root Aviation",
id1: "Kerry Waters",
id2: "Root Aviation",
dt: [
{
dt1: 1357157613919,
dt2: 1497198217881,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Kerry Waters-White Wolfoods",
id1: "Kerry Waters",
id2: "White Wolfoods",
dt: [
{
dt1: 1186565644914,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Felix Floyd-Greenetworks",
id1: "Felix Floyd",
id2: "Greenetworks",
dt: [
{
dt1: 1281749075420,
dt2: 1425911470613,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Noel Luna-Honeytelligence",
id1: "Noel Luna",
id2: "Honeytelligence",
dt: [
{
dt1: 1428549346398,
dt2: 1497935675353,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Tami Lindsey-Tempestechnologies",
id1: "Tami Lindsey",
id2: "Tempestechnologies",
dt: [
{
dt1: 1345276788162,
dt2: 1402559251417,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Tami Lindsey-Phoenixland",
id1: "Tami Lindsey",
id2: "Phoenixland",
dt: [
{
dt1: 1272650321596,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Damon Douglas-Crystalsun",
id1: "Damon Douglas",
id2: "Crystalsun",
dt: [
{
dt1: 1439239127664,
dt2: 1446474483161,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Damon Douglas-Phantom Corporation",
id1: "Damon Douglas",
id2: "Phantom Corporation",
dt: [
{
dt1: 1432259515171,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Diana Greene-Melon Arts",
id1: "Diana Greene",
id2: "Melon Arts",
dt: [
{
dt1: 1250937080868,
dt2: 1272043917343,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Diana Greene-Green",
id1: "Diana Greene",
id2: "Green",
dt: [
{
dt1: 1388980546097,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gary King-Marblightning",
id1: "Gary King",
id2: "Marblightning",
dt: [
{
dt1: 1341532138270,
dt2: 1348971910953,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Cycloration",
id1: "Brooke Fields",
id2: "Cycloration",
dt: [
{
dt1: 1252224410783,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Bluetronics",
id1: "Brooke Fields",
id2: "Bluetronics",
dt: [
{
dt1: 1327698610449,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Summitechnologies",
id1: "Brooke Fields",
id2: "Summitechnologies",
dt: [
{
dt1: 1176476394850,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Cloudwalk",
id1: "Brooke Fields",
id2: "Cloudwalk",
dt: [
{
dt1: 1343570952015,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Brooke Fields-Jettechs",
id1: "Brooke Fields",
id2: "Jettechs",
dt: [
{
dt1: 1183735407623,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Quadbridge",
id1: "Gina Carlson",
id2: "Quadbridge",
dt: [
{
dt1: 1203779987419,
dt2: 1286114861583,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Crow Navigations",
id1: "Gina Carlson",
id2: "Crow Navigations",
dt: [
{
dt1: 1252864333111,
dt2: 1332066374345,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Grasshopper Co.",
id1: "Gina Carlson",
id2: "Grasshopper Co.",
dt: [
{
dt1: 1318370099782,
dt2: 1367155178043,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Daydream Security",
id1: "Gina Carlson",
id2: "Daydream Security",
dt: [
{
dt1: 1445086054970,
dt2: 1494164214919,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gina Carlson-Joytechs",
id1: "Gina Carlson",
id2: "Joytechs",
dt: [
{
dt1: 1508949404869,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Guillermo Vaughn-Dwarfoods",
id1: "Guillermo Vaughn",
id2: "Dwarfoods",
dt: [
{
dt1: 1439419710533,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Rose Ingram-Cliffoods",
id1: "Rose Ingram",
id2: "Cliffoods",
dt: [
{
dt1: 1447743740784,
dt2: 1475561870381,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Jeannie Wolfe-Vinedustries",
id1: "Jeannie Wolfe",
id2: "Vinedustries",
dt: [
{
dt1: 1302350026690,
dt2: 1362601707946,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Jeannie Wolfe-Bansheewares",
id1: "Jeannie Wolfe",
id2: "Bansheewares",
dt: [
{
dt1: 1283669644884,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Dave Rice-Moonshine",
id1: "Dave Rice",
id2: "Moonshine",
dt: [
{
dt1: 1232018923653,
dt2: 1509860168360,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Paul Watts-Mapleway",
id1: "Paul Watts",
id2: "Mapleway",
dt: [
{
dt1: 1210590359697,
dt2: 1274000597065,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Danny Matthews-Diamond Aviation",
id1: "Danny Matthews",
id2: "Diamond Aviation",
dt: [
{
dt1: 1440723155554,
dt2: 1503407220276,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Danny Matthews-Grotto Corp",
id1: "Danny Matthews",
id2: "Grotto Corp",
dt: [
{
dt1: 1411610571654,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Anthony Mitchell-Root Aviation",
id1: "Anthony Mitchell",
id2: "Root Aviation",
dt: [
{
dt1: 1412918383186,
dt2: 1433401731854,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Anthony Mitchell-White Wolfoods",
id1: "Anthony Mitchell",
id2: "White Wolfoods",
dt: [
{
dt1: 1303392645020,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Alfred Hicks-Greenetworks",
id1: "Alfred Hicks",
id2: "Greenetworks",
dt: [
{
dt1: 1245395749674,
dt2: 1343518747478,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Adrian Mcdaniel-Honeytelligence",
id1: "Adrian Mcdaniel",
id2: "Honeytelligence",
dt: [
{
dt1: 1244519754341,
dt2: 1398795162709,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Adrian Mcdaniel-Tempestechnologies",
id1: "Adrian Mcdaniel",
id2: "Tempestechnologies",
dt: [
{
dt1: 1293685825988,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Kerry Waters-Phoenixland",
id1: "Kerry Waters",
id2: "Phoenixland",
dt: [
{
dt1: 1286331465363,
dt2: 1321863520043,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Felix Floyd-Crystalsun",
id1: "Felix Floyd",
id2: "Crystalsun",
dt: [
{
dt1: 1404871089274,
dt2: 1435383669902,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Felix Floyd-Phantom Corporation",
id1: "Felix Floyd",
id2: "Phantom Corporation",
dt: [
{
dt1: 1239896796491,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Noel Luna-Melon Arts",
id1: "Noel Luna",
id2: "Melon Arts",
dt: [
{
dt1: 1232612229592,
dt2: 1489184683838,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Noel Luna-Green",
id1: "Noel Luna",
id2: "Green",
dt: [
{
dt1: 1179384154182,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Tami Lindsey-Marblightning",
id1: "Tami Lindsey",
id2: "Marblightning",
dt: [
{
dt1: 1352564813420,
dt2: 1365113284879,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Tami Lindsey-Cycloration",
id1: "Tami Lindsey",
id2: "Cycloration",
dt: [
{
dt1: 1408263996000,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Damon Douglas-Bluetronics",
id1: "Damon Douglas",
id2: "Bluetronics",
dt: [
{
dt1: 1365560827793,
dt2: 1455292661790,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Damon Douglas-Summitechnologies",
id1: "Damon Douglas",
id2: "Summitechnologies",
dt: [
{
dt1: 1371837671366,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Diana Greene-Cloudwalk",
id1: "Diana Greene",
id2: "Cloudwalk",
dt: [
{
dt1: 1368713370177,
dt2: 1505960116022,
},
],
a2: true,
w: 3,
},
{
type: "link",
id: "Gary King-Jettechs",
id1: "Gary King",
id2: "Jettechs",
dt: [
{
dt1: 1212476185184,
dt2: 1303569548447,
},
],
a2: true,
w: 3,
},
],
}; <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Vue.js Integration</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" type="text/css" href="font-awesome/css/font-awesome.css" />
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div id="kl-container"></div>
<script type="module" src="./code.js"></script>
</body>
</html> #tooltip {
position: absolute;
padding: 5px;
display: block;
color: black;
float: left;
border: 1px solid #ccc;
background-color: #fff;
z-index: 1000;
width: 208px;
}
.arrow {
position: absolute;
top: 20px;
left: -9px;
border-width: 0px 0px 1px 1px;
border-style: solid;
border-color: #ccc;
background-color: #fff;
transform: rotateZ(45deg);
height: 15px;
width: 15px;
}
.right .arrow {
top: 20px;
left: 199px;
transform: rotateZ(225deg);
}
.table-cell {
text-align: right;
padding: 5px;
}