Skip to content
  1. Examples

Tooltip (with Mustache)

This example shows how to use the legacy tooltip tool. Prefer using the tooltip plugin.

Position the cursor over a node or an edge to display a tooltip that contains some of its properties. Right-click on the background to show a tooltip that could be a contextual menu.

ts
import Ogma from '@linkurious/ogma';
import Mustache from 'mustache';

type NodeData = {
  properties: {
    funding_total: number;
    status: string;
    market: string;
    url: string;
  };
};

const ogma = new Ogma<NodeData>({
  container: 'graph-container'
});

const graph = await Ogma.parse.jsonFromUrl<NodeData>('files/solarCity.json');
await ogma.setGraph(graph);
await ogma.view.locateGraph();

const nodeTemplate =
  '<div class="arrow"></div>' +
  '<div class="ogma-tooltip-header"><span class="icon">{{icon}}</span> {{text}}</div>' +
  '<div class="ogma-tooltip-body">' +
  '  <table>' +
  '    {{#prop.funding_total}}<tr><th>Funding</th> <td>{{prop.funding_total}}</td></tr>{{/prop.funding_total}}' +
  '    {{#prop.status}}<tr><th>Status</th> <td>{{prop.status}}</td></tr>{{/prop.status}}' +
  '    {{#prop.market}}<tr><th>Market</th> <td>{{prop.market}}</td></tr>{{/prop.market}}' +
  '    {{#prop.url}}<tr><th>URL</th> <td><a href="{{prop.url}}" target="_blank">{{prop.url}}</a></td></tr>{{/prop.url}}' +
  '  </table>' +
  '</div>' +
  '<div class="ogma-tooltip-footer">Number of connections: {{degree}}</div>';

ogma.tools.tooltip.onNodeHover(
  node => {
    const view = {
      text: node.getAttribute('text.content'),
      icon: node.getAttribute('icon.content'),
      prop: node.getData('properties'),
      degree: node.getDegree()
    };
    return Mustache.render(nodeTemplate, view);
  },
  { className: 'ogma-tooltip' }
);

const edgeTemplate =
  '<div class="arrow"></div>' +
  '<div class="ogma-tooltip-header">{{sourceNode}} {{text}} {{targetNode}}</div>' +
  '<div class="ogma-tooltip-body">' +
  '  <table>' +
  '    {{#prop.raised_amount_usd}}<tr><th>Funding</th> <td>{{prop.raised_amount_usd}}</td></tr>{{/prop.raised_amount_usd}}' +
  '    {{#prop.funded_quarter}}<tr><th>Status</th> <td>{{prop.funded_quarter}}</td></tr>{{/prop.funded_quarter}}' +
  '    {{#prop.funding_round_type}}<tr><th>Market</th> <td>{{prop.funding_round_type}}</td></tr>{{/prop.funding_round_type}}' +
  '  </table>' +
  '</div>';

ogma.tools.tooltip.onEdgeHover(
  edge => {
    const view = {
      text: edge.getAttribute('text.content'),
      sourceNode: edge.getSource().getAttribute('text.content'),
      targetNode: edge.getTarget().getAttribute('text.content'),
      prop: edge.getData('properties')
    };
    return Mustache.render(edgeTemplate, view);
  },
  { className: 'ogma-tooltip' }
);

ogma.tools.tooltip.onBackgroundRightClick(
  () => '<div class="ogma-tooltip" style="padding:10px">Your menu here.</div>',
  { className: 'ogma-tooltip', position: 'right' }
);
html
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <link
      href="https://cdn.jsdelivr.net/npm/lucide-static@0.483.0/font/lucide.css"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
      rel="stylesheet"
    />
    <link type="text/css" rel="stylesheet" href="styles.css" />
  </head>

  <body>
    <div id="graph-container"></div>
    <!-- force icon font loading -->
    <i class="icon-camera" style="color: rgba(0, 0, 0, 0)"></i>
    <script type="module" src="index.ts"></script>
  </body>
</html>
css
#graph-container {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  position: absolute;
  margin: 0;
  overflow: hidden;
}

.ogma-tooltip {
  max-width: 240px;
  max-height: 280px;
  background-color: #fff;
  border: 1px solid #999;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  border-radius: 6px;
  cursor: auto;
  font-family: Arial;
  font-size: 12px;
}

.ogma-tooltip .icon {
  font-family: Lucide;
}

.ogma-tooltip-header {
  font-variant: small-caps;
  font-size: 120%;
  color: #000;
  border-bottom: 1px solid #999;
  padding: 10px;
}

.ogma-tooltip-body {
  padding: 10px;
  overflow-x: hidden;
  overflow-y: auto;
  max-width: inherit;
  max-height: 180px;
}

.ogma-tooltip-body th {
  color: #999;
  text-align: left;
}

.ogma-tooltip-footer {
  padding: 10px;
  border-top: 1px solid #999;
}

.ogma-tooltip > .arrow {
  border-width: 10px;
  position: absolute;
  display: block;
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
}

.ogma-tooltip.top {
  margin-top: -12px;
}

.ogma-tooltip.top > .arrow {
  left: 50%;
  bottom: -10px;
  margin-left: -10px;
  border-top-color: #999;
  border-bottom-width: 0;
}

.ogma-tooltip.bottom {
  margin-top: 12px;
}

.ogma-tooltip.bottom > .arrow {
  left: 50%;
  top: -10px;
  margin-left: -10px;
  border-bottom-color: #999;
  border-top-width: 0;
}

.ogma-tooltip.left {
  margin-left: -12px;
}

.ogma-tooltip.left > .arrow {
  top: 50%;
  right: -10px;
  margin-top: -10px;
  border-left-color: #999;
  border-right-width: 0;
}

.ogma-tooltip.right {
  margin-left: 12px;
}

.ogma-tooltip.right > .arrow {
  top: 50%;
  left: -10px;
  margin-top: -10px;
  border-right-color: #999;
  border-left-width: 0;
}