#1676 Adding click support to the new rendering engine and classDiagram-v2

This commit is contained in:
Knut Sveidqvist
2020-09-10 20:58:16 +02:00
parent 571b8bbd88
commit 9d8c867de8
11 changed files with 191 additions and 13 deletions

View File

@@ -7,6 +7,7 @@
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo="> <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
</head> </head>
<body> <body>
<div style="display: flex">
<div id="FirstLine" class="mermaid"> <div id="FirstLine" class="mermaid">
graph TB graph TB
Function-->URL Function-->URL
@@ -20,6 +21,23 @@
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>
<div id="FirstLine" class="mermaid">
classDiagram
class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
</div>
<div id="FirstLine" class="mermaid">
classDiagram-v2
class ShapeLink2
link ShapeLink2 "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback2
callback ShapeCallback2 "clickByClass" "This is a tooltip for a callback"
</div>
</div>
<div class="mermaid"> <div class="mermaid">
gantt gantt
dateFormat YYYY-MM-DD dateFormat YYYY-MM-DD
@@ -82,6 +100,14 @@
document.getElementsByTagName('body')[0].appendChild(div) document.getElementsByTagName('body')[0].appendChild(div)
} }
function clickByClass() {
const div = document.createElement('div')
div.className = 'created-by-class-click'
div.style = 'padding: 20px; background: purple; color: white;'
div.innerText = 'Clicked By Class'
document.getElementsByTagName('body')[0].appendChild(div)
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 }); mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script> </script>
</body> </body>

View File

@@ -0,0 +1,122 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<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">
<div id="FirstLine" class="mermaid">
graph 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="mermaid2">
graph TB
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="mermaid2">
classDiagram
class Test
class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
</div>
<div id="FirstLine" class="mermaid">
classDiagram-v2
class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
</div>
<div id="FirstLine" class="mermaid">
classDiagram-v2
class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
</div>
</div>
<div class="mermaid2">
gantt
dateFormat YYYY-MM-DD
axisFormat %d/%m
title Adding GANTT diagram to mermaid
excludes weekdays 2014-01-10
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Clickable
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d
click cl1 href "http://localhost:9000/webpackUsage.html"
click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3)
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
</div>
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div')
div.className = 'created-by-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Flow'
document.getElementsByTagName('body')[0].appendChild(div)
}
function clickByGantt(arg1, arg2, arg3) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div)
}
function clickByClass() {
const div = document.createElement('div')
div.className = 'created-by-class-click'
div.style = 'padding: 20px; background: purple; color: white;'
div.innerText = 'Clicked By Class'
document.getElementsByTagName('body')[0].appendChild(div)
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script>
</body>
</html>

View File

@@ -289,7 +289,7 @@ const rectWithTitle = (parent, node) => {
const shapeSvg = parent const shapeSvg = parent
.insert('g') .insert('g')
.attr('class', classes) .attr('class', classes)
.attr('id', node.id); .attr('id', node.domId || node.id);
// 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');
@@ -458,7 +458,7 @@ const start = (parent, node) => {
const shapeSvg = parent const shapeSvg = parent
.insert('g') .insert('g')
.attr('class', 'node default') .attr('class', 'node default')
.attr('id', node.id); .attr('id', node.domId || node.id);
const circle = shapeSvg.insert('circle', ':first-child'); const circle = shapeSvg.insert('circle', ':first-child');
// center the circle around its coordinate // center the circle around its coordinate
@@ -481,7 +481,7 @@ const forkJoin = (parent, node, dir) => {
const shapeSvg = parent const shapeSvg = parent
.insert('g') .insert('g')
.attr('class', 'node default') .attr('class', 'node default')
.attr('id', node.id); .attr('id', node.domId || node.id);
let width = 70; let width = 70;
let height = 10; let height = 10;
@@ -515,7 +515,7 @@ const end = (parent, node) => {
const shapeSvg = parent const shapeSvg = parent
.insert('g') .insert('g')
.attr('class', 'node default') .attr('class', 'node default')
.attr('id', node.id); .attr('id', node.domId || node.id);
const innerCircle = shapeSvg.insert('circle', ':first-child'); const innerCircle = shapeSvg.insert('circle', ':first-child');
const circle = shapeSvg.insert('circle', ':first-child'); const circle = shapeSvg.insert('circle', ':first-child');
@@ -552,10 +552,18 @@ const class_box = (parent, node) => {
classes = 'node ' + node.classes; classes = 'node ' + node.classes;
} }
// Add outer g element // Add outer g element
const shapeSvg = parent const shapeSvgG = parent
.insert('g') .insert('g')
.attr('class', classes) .attr('class', classes)
.attr('id', 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');
@@ -823,6 +831,9 @@ let nodeElems = {};
export const insertNode = (elem, node, dir) => { export const insertNode = (elem, node, dir) => {
nodeElems[node.id] = shapes[node.shape](elem, node, dir); nodeElems[node.id] = shapes[node.shape](elem, node, dir);
if (node.haveCallback) {
nodeElems[node.id].attr('class', nodeElems[node.id].attr('class') + ' clickable');
}
}; };
export const setNodeElem = (elem, node) => { export const setNodeElem = (elem, node) => {
nodeElems[node.id] = elem; nodeElems[node.id] = elem;

View File

@@ -12,7 +12,7 @@ export const labelHelper = (parent, node, _classes, isNode) => {
const shapeSvg = parent const shapeSvg = parent
.insert('g') .insert('g')
.attr('class', classes) .attr('class', classes)
.attr('id', node.id); .attr('id', node.domId || node.id);
// Create the label and insert it after the rect // Create the label and insert it after the rect
const label = shapeSvg.insert('g').attr('class', 'label'); const label = shapeSvg.insert('g').attr('class', 'label');

View File

@@ -7,8 +7,6 @@ import mermaidAPI from '../../mermaidAPI';
const MERMAID_DOM_ID_PREFIX = 'classid-'; const MERMAID_DOM_ID_PREFIX = 'classid-';
const config = configApi.getConfig();
let relations = []; let relations = [];
let classes = {}; let classes = {};
let classCounter = 0; let classCounter = 0;
@@ -176,6 +174,7 @@ export const setCssClass = function(ids, className) {
* @param tooltip Tooltip for the clickable element * @param tooltip Tooltip for the clickable element
*/ */
export const setLink = function(ids, linkStr, tooltip) { export const setLink = function(ids, linkStr, tooltip) {
const config = configApi.getConfig();
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;
@@ -199,11 +198,13 @@ export const setLink = function(ids, linkStr, tooltip) {
export const setClickEvent = function(ids, functionName, tooltip) { export const setClickEvent = function(ids, functionName, tooltip) {
ids.split(',').forEach(function(id) { ids.split(',').forEach(function(id) {
setClickFunc(id, functionName, tooltip); setClickFunc(id, functionName, tooltip);
classes[id].haveCallback = true;
}); });
setCssClass(ids, 'clickable'); setCssClass(ids, 'clickable');
}; };
const setClickFunc = function(domId, functionName, tooltip) { const setClickFunc = function(domId, functionName, tooltip) {
const config = configApi.getConfig();
let id = domId; let id = domId;
let elemId = lookUpDomId(id); let elemId = lookUpDomId(id);

View File

@@ -34,6 +34,7 @@ export const addClasses = function(classes, g) {
logger.info('keys:', keys); logger.info('keys:', keys);
logger.info(classes); logger.info(classes);
let cnt = 0;
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
keys.forEach(function(id) { keys.forEach(function(id) {
const vertex = classes[id]; const vertex = classes[id];
@@ -101,11 +102,16 @@ export const addClasses = function(classes, g) {
class: classStr, class: classStr,
style: styles.style, style: styles.style,
id: vertex.id, id: vertex.id,
domId: vertex.domId,
haveCallback: vertex.haveCallback,
link: vertex.link,
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
}); });
cnt++;
logger.info('setNode', { logger.info('setNode', {
labelStyle: styles.labelStyle, labelStyle: styles.labelStyle,
shape: _shape, shape: _shape,

View File

@@ -29,6 +29,7 @@ export const addVertices = function(vert, g, svgId) {
const keys = Object.keys(vert); const keys = Object.keys(vert);
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
let cnt = 0;
keys.forEach(function(id) { keys.forEach(function(id) {
const vertex = vert[id]; const vertex = vert[id];
@@ -141,6 +142,9 @@ export const addVertices = function(vert, g, svgId) {
class: classStr, class: classStr,
style: styles.style, style: styles.style,
id: vertex.id, id: vertex.id,
link: vertex.link,
linkTarget: vertex.linkTarget,
domId: 'flow-' + vertex.id + '-' + cnt,
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
@@ -155,10 +159,12 @@ 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,
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
}); });
cnt++;
}); });
}; };

View File

@@ -301,7 +301,6 @@ export const draw = function(text, id) {
} }
let secNum = 0; let secNum = 0;
console.log(conf);
for (let i = 0; i < categories.length; i++) { for (let i = 0; i < categories.length; i++) {
if (d.type === categories[i]) { if (d.type === categories[i]) {
secNum = i % conf.numberSectionStyles; secNum = i % conf.numberSectionStyles;

View File

@@ -100,6 +100,7 @@ const setupNode = (g, parent, node, altFlag) => {
classes: nodeDb[node.id].classes, //classStr, classes: nodeDb[node.id].classes, //classStr,
style: '', //styles.style, style: '', //styles.style,
id: node.id, id: node.id,
domId: 'state-' + node.id + '-' + cnt,
type: nodeDb[node.id].type, type: nodeDb[node.id].type,
padding: 15 //getConfig().flowchart.padding padding: 15 //getConfig().flowchart.padding
}; };
@@ -113,6 +114,7 @@ const setupNode = (g, parent, node, altFlag) => {
classes: 'statediagram-note', //classStr, classes: 'statediagram-note', //classStr,
style: '', //styles.style, style: '', //styles.style,
id: node.id + '----note', id: node.id + '----note',
domId: 'state-' + node.id + '----note-' + cnt,
type: nodeDb[node.id].type, type: nodeDb[node.id].type,
padding: 15 //getConfig().flowchart.padding padding: 15 //getConfig().flowchart.padding
}; };
@@ -123,9 +125,12 @@ const setupNode = (g, parent, node, altFlag) => {
classes: nodeDb[node.id].classes, //classStr, classes: nodeDb[node.id].classes, //classStr,
style: '', //styles.style, style: '', //styles.style,
id: node.id + '----parent', id: node.id + '----parent',
domId: 'state-' + node.id + '----parent-' + cnt,
type: 'group', type: 'group',
padding: 0 //getConfig().flowchart.padding padding: 0 //getConfig().flowchart.padding
}; };
cnt++;
g.setNode(node.id + '----parent', groupData); g.setNode(node.id + '----parent', groupData);
g.setNode(noteData.id, noteData); g.setNode(noteData.id, noteData);
@@ -170,6 +175,7 @@ const setupNode = (g, parent, node, altFlag) => {
}; };
let cnt = 0; let cnt = 0;
const setupDoc = (g, parent, doc, altFlag) => { const setupDoc = (g, parent, doc, altFlag) => {
cnt = 0;
logger.trace('items', doc); logger.trace('items', doc);
doc.forEach(item => { doc.forEach(item => {
if (item.stmt === 'state' || item.stmt === 'default') { if (item.stmt === 'state' || item.stmt === 'default') {

View File

@@ -220,7 +220,7 @@ const render = function(id, _txt, cb, container) {
// console.warn('Render fetching config'); // console.warn('Render fetching config');
const cnf = configApi.getConfig(); const cnf = configApi.getConfig();
console.warn('Render with config after adding new directives', cnf.sequence); // console.warn('Render with config after adding new directives', cnf.sequence);
// console.warn( // console.warn(
// 'Render with config after adding new directives', // 'Render with config after adding new directives',
// cnf.fontFamily, // cnf.fontFamily,
@@ -437,6 +437,7 @@ const render = function(id, _txt, cb, container) {
cb(svgCode, ganttDb.bindFunctions); cb(svgCode, ganttDb.bindFunctions);
break; break;
case 'class': case 'class':
case 'classDiagram':
cb(svgCode, classDb.bindFunctions); cb(svgCode, classDb.bindFunctions);
break; break;
default: default: