diff --git a/cypress/platform/click_security_loose.html b/cypress/platform/click_security_loose.html
index dab82f983..8d7b7f244 100644
--- a/cypress/platform/click_security_loose.html
+++ b/cypress/platform/click_security_loose.html
@@ -5,6 +5,11 @@
Mermaid Quick Test Page
+
@@ -16,7 +21,19 @@
graph TB
- 1Function-->2URL
+ 1Function--->2URL
+ click 1Function clickByFlow "Add a div"
+ click 2URL "http://localhost:9000/webpackUsage.html" "Visit mermaid docs"
+
+
+ flowchart TB
+ Function-->URL
+ click Function clickByFlow "Add a div"
+ click URL "http://localhost:9000/webpackUsage.html" "Visit mermaid docs"
+
+
+ flowchart TB
+ 1Function--->2URL
click 1Function clickByFlow "Add a div"
click 2URL "http://localhost:9000/webpackUsage.html" "Visit mermaid docs"
diff --git a/src/dagre-wrapper/nodes.js b/src/dagre-wrapper/nodes.js
index 086919241..485b56abf 100644
--- a/src/dagre-wrapper/nodes.js
+++ b/src/dagre-wrapper/nodes.js
@@ -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');
}
diff --git a/src/diagrams/flowchart/flowDb.js b/src/diagrams/flowchart/flowDb.js
index 6be1f2c18..d70d56433 100644
--- a/src/diagrams/flowchart/flowDb.js
+++ b/src/diagrams/flowchart/flowDb.js
@@ -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,
diff --git a/src/diagrams/flowchart/flowRenderer-v2.js b/src/diagrams/flowchart/flowRenderer-v2.js
index e9548b5b5..a3b9472ab 100644
--- a/src/diagrams/flowchart/flowRenderer-v2.js
+++ b/src/diagrams/flowchart/flowRenderer-v2.js
@@ -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');