#1676 Adding click support and tooltip support for flowchart

This commit is contained in:
Knut Sveidqvist 2020-09-12 10:56:23 +02:00
parent 6360ed52b2
commit c8c4554299
4 changed files with 79 additions and 54 deletions

View File

@ -5,6 +5,11 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
<style>
.mermaid2 {
display: none;
}
</style>
</head>
<body>
<div style="display: flex">
@ -16,7 +21,19 @@
</div>
<div id="FirstLine" class="mermaid">
graph TB
1Function-->2URL
1Function--->2URL
click 1Function clickByFlow "Add a div"
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</div>
<div id="FirstLine" class="mermaid">
flowchart TB
Function-->URL
click Function clickByFlow "Add a div"
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</div>
<div id="FirstLine" class="mermaid">
flowchart TB
1Function--->2URL
click 1Function clickByFlow "Add a div"
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</div>

View File

@ -552,19 +552,11 @@ const class_box = (parent, node) => {
classes = 'node ' + node.classes;
}
// Add outer g element
const shapeSvgG = parent
const shapeSvg = parent
.insert('g')
.attr('class', classes)
.attr('id', node.domId || node.id);
// Add link
const shapeSvg = node.link
? shapeSvgG
.append('svg:a')
.attr('xlink:href', node.link)
.attr('target', node.linkTarget || '_blank')
: shapeSvgG;
// Create the title label and insert it after the rect
const rect = shapeSvg.insert('rect', ':first-child');
const topLine = shapeSvg.insert('line');
@ -830,7 +822,26 @@ const shapes = {
let nodeElems = {};
export const insertNode = (elem, node, dir) => {
nodeElems[node.id] = shapes[node.shape](elem, node, dir);
let newEl;
let el;
// Add link when appropriate
if (node.link) {
newEl = elem
.insert('svg:a')
.attr('xlink:href', node.link)
.attr('target', node.linkTarget || '_blank');
el = shapes[node.shape](newEl, node, dir);
} else {
el = shapes[node.shape](elem, node, dir);
newEl = el;
}
if (node.tooltip) {
el.attr('title', node.tooltip);
}
nodeElems[node.id] = newEl;
if (node.haveCallback) {
nodeElems[node.id].attr('class', nodeElems[node.id].attr('class') + ' clickable');
}

View File

@ -5,8 +5,8 @@ import common from '../common/common';
import mermaidAPI from '../../mermaidAPI';
// const MERMAID_DOM_ID_PREFIX = 'mermaid-dom-id-';
const MERMAID_DOM_ID_PREFIX = '';
const MERMAID_DOM_ID_PREFIX = 'flowchart-';
let vertexCounter = 0;
let config = configApi.getConfig();
let vertices = {};
let edges = [];
@ -24,6 +24,20 @@ export const parseDirective = function(statement, context, type) {
mermaidAPI.parseDirective(this, statement, context, type);
};
/**
* Function to lookup domId from id in the graph definition.
* @param id
* @public
*/
export const lookUpDomId = function(id) {
const veritceKeys = Object.keys(vertices);
for (let i = 0; i < veritceKeys.length; i++) {
if (vertices[veritceKeys[i]].id === id) {
return vertices[veritceKeys[i]].domId;
}
}
};
/**
* Function called by parser when a node definition has been found
* @param id
@ -42,11 +56,17 @@ export const addVertex = function(_id, text, type, style, classes) {
return;
}
if (id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
// if (id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof vertices[id] === 'undefined') {
vertices[id] = { id: id, styles: [], classes: [] };
vertices[id] = {
id: id,
domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter,
styles: [],
classes: []
};
}
vertexCounter++;
if (typeof text !== 'undefined') {
config = configApi.getConfig();
txt = common.sanitizeText(text.trim(), config);
@ -91,8 +111,8 @@ export const addVertex = function(_id, text, type, style, classes) {
export const addSingleLink = function(_start, _end, type, linktext) {
let start = _start;
let end = _end;
if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
// if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
// if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
// logger.info('Got edge...', start, end);
const edge = { start: start, end: end, type: undefined, text: '' };
@ -203,7 +223,7 @@ export const setDirection = function(dir) {
export const setClass = function(ids, className) {
ids.split(',').forEach(function(_id) {
let id = _id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof vertices[id] !== 'undefined') {
vertices[id].classes.push(className);
}
@ -222,9 +242,9 @@ const setTooltip = function(ids, tooltip) {
});
};
const setClickFun = function(_id, functionName) {
let id = _id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
const setClickFun = function(id, functionName) {
let domId = lookUpDomId(id);
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (configApi.getConfig().securityLevel !== 'loose') {
return;
}
@ -232,8 +252,9 @@ const setClickFun = function(_id, functionName) {
return;
}
if (typeof vertices[id] !== 'undefined') {
vertices[id].haveCallback = true;
funs.push(function() {
const elem = document.querySelector(`[id="${id}"]`);
const elem = document.querySelector(`[id="${domId}"]`);
if (elem !== null) {
elem.addEventListener(
'click',
@ -254,9 +275,9 @@ const setClickFun = function(_id, functionName) {
* @param tooltip Tooltip for the clickable element
*/
export const setLink = function(ids, linkStr, tooltip, target) {
ids.split(',').forEach(function(_id) {
let id = _id;
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
ids.split(',').forEach(function(id) {
// let domId = lookUpDomId(id);
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof vertices[id] !== 'undefined') {
vertices[id].link = utils.formatUrl(linkStr, config);
vertices[id].linkTarget = target;
@ -638,6 +659,7 @@ export default {
parseDirective,
defaultConfig: () => configApi.defaultConfig.flowchart,
addVertex,
lookUpDomId,
addLink,
updateLinkInterpolate,
updateLink,

View File

@ -144,7 +144,9 @@ export const addVertices = function(vert, g, svgId) {
id: vertex.id,
link: vertex.link,
linkTarget: vertex.linkTarget,
domId: 'flow-' + vertex.id + '-' + cnt,
tooltip: flowDb.getTooltip(vertex.id) || '',
domId: flowDb.lookUpDomId(vertex.id),
haveCallback: vertex.haveCallback,
width: vertex.type === 'group' ? 500 : undefined,
type: vertex.type,
padding: getConfig().flowchart.padding
@ -159,7 +161,7 @@ export const addVertices = function(vert, g, svgId) {
class: classStr,
style: styles.style,
id: vertex.id,
domId: 'flow-' + vertex.id + '-' + cnt,
domId: flowDb.lookUpDomId(vertex.id),
width: vertex.type === 'group' ? 500 : undefined,
type: vertex.type,
padding: getConfig().flowchart.padding
@ -411,11 +413,6 @@ export const draw = function(text, id) {
// Run the renderer. This is what draws the final graph.
const element = select('#' + id + ' g');
render(element, g, ['point', 'circle', 'cross'], 'flowchart', id);
// dagre.layout(g);
element.selectAll('g.node').attr('title', function() {
return flowDb.getTooltip(this.id);
});
const padding = conf.diagramPadding;
const svgBounds = svg.node().getBBox();
@ -436,28 +433,6 @@ export const draw = function(text, id) {
// Index nodes
flowDb.indexNodes('subGraph' + i);
// // reposition labels
// for (i = 0; i < subGraphs.length; i++) {
// subG = subGraphs[i];
// if (subG.title !== 'undefined') {
// const clusterRects = document.querySelectorAll('#' + id + ' [id="' + subG.id + '"] rect');
// const clusterEl = document.querySelectorAll('#' + id + ' [id="' + subG.id + '"]');
// const xPos = clusterRects[0].x.baseVal.value;
// const yPos = clusterRects[0].y.baseVal.value;
// const width = clusterRects[0].width.baseVal.value;
// const cluster = d3.select(clusterEl[0]);
// const te = cluster.select('.label');
// te.attr('transform', `translate(${xPos + width / 2}, ${yPos + 14})`);
// te.attr('id', id + 'Text');
// for (let j = 0; j < subG.classes.length; j++) {
// clusterEl[0].classList.add(subG.classes[j]);
// }
// }
// }
// Add label rects for non html labels
if (!conf.htmlLabels) {
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');