mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
#1676 Adding click support and tooltip support for flowchart
This commit is contained in:
parent
6360ed52b2
commit
c8c4554299
@ -5,6 +5,11 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<title>Mermaid Quick Test Page</title>
|
<title>Mermaid Quick Test Page</title>
|
||||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
|
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
|
||||||
|
<style>
|
||||||
|
.mermaid2 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
@ -16,7 +21,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="FirstLine" class="mermaid">
|
<div id="FirstLine" class="mermaid">
|
||||||
graph TB
|
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 1Function clickByFlow "Add a div"
|
||||||
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
||||||
</div>
|
</div>
|
||||||
|
@ -552,19 +552,11 @@ const class_box = (parent, node) => {
|
|||||||
classes = 'node ' + node.classes;
|
classes = 'node ' + node.classes;
|
||||||
}
|
}
|
||||||
// Add outer g element
|
// Add outer g element
|
||||||
const shapeSvgG = parent
|
const shapeSvg = parent
|
||||||
.insert('g')
|
.insert('g')
|
||||||
.attr('class', classes)
|
.attr('class', classes)
|
||||||
.attr('id', node.domId || node.id);
|
.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
|
// Create the title label and insert it after the rect
|
||||||
const rect = shapeSvg.insert('rect', ':first-child');
|
const rect = shapeSvg.insert('rect', ':first-child');
|
||||||
const topLine = shapeSvg.insert('line');
|
const topLine = shapeSvg.insert('line');
|
||||||
@ -830,7 +822,26 @@ const shapes = {
|
|||||||
let nodeElems = {};
|
let nodeElems = {};
|
||||||
|
|
||||||
export const insertNode = (elem, node, dir) => {
|
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) {
|
if (node.haveCallback) {
|
||||||
nodeElems[node.id].attr('class', nodeElems[node.id].attr('class') + ' clickable');
|
nodeElems[node.id].attr('class', nodeElems[node.id].attr('class') + ' clickable');
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import common from '../common/common';
|
|||||||
import mermaidAPI from '../../mermaidAPI';
|
import mermaidAPI from '../../mermaidAPI';
|
||||||
|
|
||||||
// const MERMAID_DOM_ID_PREFIX = 'mermaid-dom-id-';
|
// 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 config = configApi.getConfig();
|
||||||
let vertices = {};
|
let vertices = {};
|
||||||
let edges = [];
|
let edges = [];
|
||||||
@ -24,6 +24,20 @@ export const parseDirective = function(statement, context, type) {
|
|||||||
mermaidAPI.parseDirective(this, 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
|
* Function called by parser when a node definition has been found
|
||||||
* @param id
|
* @param id
|
||||||
@ -42,11 +56,17 @@ export const addVertex = function(_id, text, type, style, classes) {
|
|||||||
return;
|
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') {
|
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') {
|
if (typeof text !== 'undefined') {
|
||||||
config = configApi.getConfig();
|
config = configApi.getConfig();
|
||||||
txt = common.sanitizeText(text.trim(), config);
|
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) {
|
export const addSingleLink = function(_start, _end, type, linktext) {
|
||||||
let start = _start;
|
let start = _start;
|
||||||
let end = _end;
|
let end = _end;
|
||||||
if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
|
// if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start;
|
||||||
if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
|
// if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end;
|
||||||
// logger.info('Got edge...', start, end);
|
// logger.info('Got edge...', start, end);
|
||||||
|
|
||||||
const edge = { start: start, end: end, type: undefined, text: '' };
|
const edge = { start: start, end: end, type: undefined, text: '' };
|
||||||
@ -203,7 +223,7 @@ export const setDirection = function(dir) {
|
|||||||
export const setClass = function(ids, className) {
|
export const setClass = function(ids, className) {
|
||||||
ids.split(',').forEach(function(_id) {
|
ids.split(',').forEach(function(_id) {
|
||||||
let id = _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') {
|
if (typeof vertices[id] !== 'undefined') {
|
||||||
vertices[id].classes.push(className);
|
vertices[id].classes.push(className);
|
||||||
}
|
}
|
||||||
@ -222,9 +242,9 @@ const setTooltip = function(ids, tooltip) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const setClickFun = function(_id, functionName) {
|
const setClickFun = function(id, functionName) {
|
||||||
let id = _id;
|
let domId = lookUpDomId(id);
|
||||||
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
|
// if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
|
||||||
if (configApi.getConfig().securityLevel !== 'loose') {
|
if (configApi.getConfig().securityLevel !== 'loose') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -232,8 +252,9 @@ const setClickFun = function(_id, functionName) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof vertices[id] !== 'undefined') {
|
if (typeof vertices[id] !== 'undefined') {
|
||||||
|
vertices[id].haveCallback = true;
|
||||||
funs.push(function() {
|
funs.push(function() {
|
||||||
const elem = document.querySelector(`[id="${id}"]`);
|
const elem = document.querySelector(`[id="${domId}"]`);
|
||||||
if (elem !== null) {
|
if (elem !== null) {
|
||||||
elem.addEventListener(
|
elem.addEventListener(
|
||||||
'click',
|
'click',
|
||||||
@ -254,9 +275,9 @@ const setClickFun = function(_id, functionName) {
|
|||||||
* @param tooltip Tooltip for the clickable element
|
* @param tooltip Tooltip for the clickable element
|
||||||
*/
|
*/
|
||||||
export const setLink = function(ids, linkStr, tooltip, target) {
|
export const setLink = function(ids, linkStr, tooltip, target) {
|
||||||
ids.split(',').forEach(function(_id) {
|
ids.split(',').forEach(function(id) {
|
||||||
let id = _id;
|
// let domId = lookUpDomId(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') {
|
if (typeof vertices[id] !== 'undefined') {
|
||||||
vertices[id].link = utils.formatUrl(linkStr, config);
|
vertices[id].link = utils.formatUrl(linkStr, config);
|
||||||
vertices[id].linkTarget = target;
|
vertices[id].linkTarget = target;
|
||||||
@ -638,6 +659,7 @@ export default {
|
|||||||
parseDirective,
|
parseDirective,
|
||||||
defaultConfig: () => configApi.defaultConfig.flowchart,
|
defaultConfig: () => configApi.defaultConfig.flowchart,
|
||||||
addVertex,
|
addVertex,
|
||||||
|
lookUpDomId,
|
||||||
addLink,
|
addLink,
|
||||||
updateLinkInterpolate,
|
updateLinkInterpolate,
|
||||||
updateLink,
|
updateLink,
|
||||||
|
@ -144,7 +144,9 @@ export const addVertices = function(vert, g, svgId) {
|
|||||||
id: vertex.id,
|
id: vertex.id,
|
||||||
link: vertex.link,
|
link: vertex.link,
|
||||||
linkTarget: vertex.linkTarget,
|
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,
|
width: vertex.type === 'group' ? 500 : undefined,
|
||||||
type: vertex.type,
|
type: vertex.type,
|
||||||
padding: getConfig().flowchart.padding
|
padding: getConfig().flowchart.padding
|
||||||
@ -159,7 +161,7 @@ export const addVertices = function(vert, g, svgId) {
|
|||||||
class: classStr,
|
class: classStr,
|
||||||
style: styles.style,
|
style: styles.style,
|
||||||
id: vertex.id,
|
id: vertex.id,
|
||||||
domId: 'flow-' + vertex.id + '-' + cnt,
|
domId: flowDb.lookUpDomId(vertex.id),
|
||||||
width: vertex.type === 'group' ? 500 : undefined,
|
width: vertex.type === 'group' ? 500 : undefined,
|
||||||
type: vertex.type,
|
type: vertex.type,
|
||||||
padding: getConfig().flowchart.padding
|
padding: getConfig().flowchart.padding
|
||||||
@ -411,11 +413,6 @@ export const draw = function(text, id) {
|
|||||||
// Run the renderer. This is what draws the final graph.
|
// Run the renderer. This is what draws the final graph.
|
||||||
const element = select('#' + id + ' g');
|
const element = select('#' + id + ' g');
|
||||||
render(element, g, ['point', 'circle', 'cross'], 'flowchart', id);
|
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 padding = conf.diagramPadding;
|
||||||
const svgBounds = svg.node().getBBox();
|
const svgBounds = svg.node().getBBox();
|
||||||
@ -436,28 +433,6 @@ export const draw = function(text, id) {
|
|||||||
// Index nodes
|
// Index nodes
|
||||||
flowDb.indexNodes('subGraph' + i);
|
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
|
// Add label rects for non html labels
|
||||||
if (!conf.htmlLabels) {
|
if (!conf.htmlLabels) {
|
||||||
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user