mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Draft implementation of tooltips and hyperlinks as described in issue #34. More tests and documentation to follow.
This commit is contained in:
parent
30a755221b
commit
e406fda9cd
178
dist/mermaid.js
vendored
178
dist/mermaid.js
vendored
File diff suppressed because one or more lines are too long
6
dist/mermaid.min.js
vendored
6
dist/mermaid.min.js
vendored
File diff suppressed because one or more lines are too long
178
dist/mermaid.slim.js
vendored
178
dist/mermaid.slim.js
vendored
File diff suppressed because one or more lines are too long
18
dist/mermaid.slim.min.js
vendored
18
dist/mermaid.slim.min.js
vendored
File diff suppressed because one or more lines are too long
175
dist/mermaidAPI.js
vendored
175
dist/mermaidAPI.js
vendored
File diff suppressed because one or more lines are too long
177
dist/mermaidAPI.slim.js
vendored
177
dist/mermaidAPI.slim.js
vendored
File diff suppressed because one or more lines are too long
8
dist/mermaidAPI.slim.min.js
vendored
8
dist/mermaidAPI.slim.min.js
vendored
File diff suppressed because one or more lines are too long
5
dist/www/javascripts/lib/mermaid.js
vendored
5
dist/www/javascripts/lib/mermaid.js
vendored
@ -32202,7 +32202,8 @@ exports.getClasses = function (text, isDot) {
|
||||
// Add default class if undefined
|
||||
if(typeof(classes.default) === 'undefined') {
|
||||
classes.default = {id:'default'};
|
||||
classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
|
||||
//classes.default.styles = ['fill:#ffa','stroke:#666','stroke-width:3px'];
|
||||
classes.default.styles = [];
|
||||
classes.default.clusterStyles = ['rx:4px','fill: rgb(255, 255, 222)','rx: 4px','stroke: rgb(170, 170, 51)','stroke-width: 1px'];
|
||||
classes.default.nodeLabelStyles = ['fill:#000','stroke:none','font-weight:300','font-family:"Helvetica Neue",Helvetica,Arial,sans-serf','font-size:14px'];
|
||||
classes.default.edgeLabelStyles = ['fill:#000','stroke:none','font-weight:300','font-family:"Helvetica Neue",Helvetica,Arial,sans-serf','font-size:14px'];
|
||||
@ -38220,7 +38221,7 @@ module.exports.cloneCssStyles = function(svg, classes){
|
||||
if (classes.hasOwnProperty(className) && typeof(className) != "undefined") {
|
||||
if (className === 'default') {
|
||||
if (classes.default.styles instanceof Array) {
|
||||
defaultStyles += "#" + svg.id.trim() + ' .node' + ' { ' + classes[className].styles.join("; ") + '; }\n';
|
||||
defaultStyles += "#" + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join("; ") + '; }\n';
|
||||
}
|
||||
if (classes.default.nodeLabelStyles instanceof Array) {
|
||||
defaultStyles += "#" + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join("; ") + '; }\n';
|
||||
|
@ -105,6 +105,10 @@ exports.addVertices = function (vert, g) {
|
||||
case 'circle':
|
||||
_shape = 'circle';
|
||||
break;
|
||||
case 'group':
|
||||
_shape = 'rect';
|
||||
verticeText = '';
|
||||
break;
|
||||
default:
|
||||
_shape = 'rect';
|
||||
}
|
||||
@ -277,7 +281,7 @@ exports.draw = function (text, id,isDot) {
|
||||
var i = 0;
|
||||
for(i=subGraphs.length-1;i>=0;i--){
|
||||
subG = subGraphs[i];
|
||||
graph.addVertex(subG.id,undefined,undefined,undefined);
|
||||
graph.addVertex(subG.id,subG.title,'group',undefined);
|
||||
}
|
||||
|
||||
// Fetch the verices/nodes and edges/links from the parsed graph definition
|
||||
@ -394,7 +398,19 @@ exports.draw = function (text, id,isDot) {
|
||||
svgGroup = d3.select("#" + id + " g");
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(d3.select("#" + id + " g"), g);
|
||||
var element = d3.select("#" + id + " g");
|
||||
render(element, g);
|
||||
|
||||
//var tip = d3.tip().html(function(d) { return d; });
|
||||
element.selectAll("g.node")
|
||||
.attr("title", function(){
|
||||
return graph.getTooltip(this.id);
|
||||
});
|
||||
|
||||
//
|
||||
//element.selectAll("g.node")
|
||||
// .attr("title", function(v) { return styleTooltip(v, g.node(v).description) })
|
||||
// .each(function(v) { $(this).tipsy({ gravity: "w", opacity: 1, html: true }); });
|
||||
var svgb = document.querySelector("#" + id);
|
||||
|
||||
/*
|
||||
@ -430,7 +446,7 @@ exports.draw = function (text, id,isDot) {
|
||||
|
||||
|
||||
// Index nodes
|
||||
graph.indexNodes('sunGraph'+i);
|
||||
graph.indexNodes('subGraph'+i);
|
||||
|
||||
for(i=0;i<subGraphs.length;i++){
|
||||
var pos = graph.getDepthFirstPos(i);
|
||||
|
@ -6,6 +6,7 @@ var vertices = {};
|
||||
var edges = [];
|
||||
var classes = [];
|
||||
var subGraphs = [];
|
||||
var tooltips = {};
|
||||
var subCount=0;
|
||||
var direction;
|
||||
// Functions to be run after graph rendering
|
||||
@ -136,48 +137,69 @@ exports.setClass = function (id,className) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setTooltip = function(id,tooltip){
|
||||
if(typeof tooltip !== 'undefined'){
|
||||
tooltips[id]=tooltip;
|
||||
}
|
||||
};
|
||||
|
||||
var setClickFun = function(id, functionName){
|
||||
if(typeof functionName === 'undefined'){
|
||||
return;
|
||||
}
|
||||
if (typeof vertices[id] !== 'undefined') {
|
||||
funs.push(function (element) {
|
||||
var elem = d3.select(element).select('#'+id);
|
||||
if (elem !== null) {
|
||||
elem.on('click', function () {
|
||||
eval(functionName + '(\'' + id + '\')'); // jshint ignore:line
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var setLink = function(id, linkStr){
|
||||
if(typeof linkStr === 'undefined'){
|
||||
return;
|
||||
}
|
||||
if (typeof vertices[id] !== 'undefined') {
|
||||
funs.push(function (element) {
|
||||
var elem = d3.select(element).select('#'+id);
|
||||
if (elem !== null) {
|
||||
elem.on('click', function () {
|
||||
window.open(linkStr,'newTab'); // jshint ignore:line
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.getTooltip = function(id){
|
||||
return tooltips[id];
|
||||
};
|
||||
var clickEvents = [];
|
||||
/**
|
||||
* Called by parser when a graph definition is found, stores the direction of the chart.
|
||||
* @param dir
|
||||
*/
|
||||
exports.setClickEvent = function (id,functionName) {
|
||||
|
||||
|
||||
exports.setClickEvent = function (id,functionName, link,tooltip) {
|
||||
if(id.indexOf(',')>0){
|
||||
id.split(',').forEach(function(id2) {
|
||||
if (typeof vertices[id2] !== 'undefined') {
|
||||
funs.push(function () {
|
||||
var elem = document.getElementById(id2);
|
||||
if (elem !== null) {
|
||||
elem.onclick = function () {
|
||||
eval(functionName + '(\'' + id2 + '\')'); // jshint ignore:line
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
setTooltip(id2,tooltip);
|
||||
setClickFun(id2, functionName);
|
||||
setLink(id2, link);
|
||||
});
|
||||
}else{
|
||||
//log.debug('Checking now for ::'+id);
|
||||
if(typeof vertices[id] !== 'undefined'){
|
||||
funs.push(function(){
|
||||
var elem = document.getElementById(id);
|
||||
if(elem !== null){
|
||||
elem.onclick = function(){eval(functionName+'(\'' + id + '\')');}; // jshint ignore:line
|
||||
}
|
||||
else{
|
||||
//log.debug('id was null: '+id);
|
||||
}
|
||||
});
|
||||
}
|
||||
setTooltip(id,tooltip);
|
||||
setClickFun(id, functionName);
|
||||
setLink(id, link);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
exports.bindFunctions = function(){
|
||||
exports.bindFunctions = function(element){
|
||||
funs.forEach(function(fun){
|
||||
fun();
|
||||
fun(element);
|
||||
});
|
||||
};
|
||||
exports.getDirection = function () {
|
||||
@ -207,6 +229,49 @@ exports.getClasses = function () {
|
||||
return classes;
|
||||
};
|
||||
|
||||
var setupToolTips = function(element){
|
||||
|
||||
var tooltipElem = d3.select('.mermaidTooltip');
|
||||
if(tooltipElem[0][0] === null){
|
||||
tooltipElem = d3.select("body")
|
||||
.append("div")
|
||||
.attr("class", "mermaidTooltip")
|
||||
.style("opacity", 0);
|
||||
}
|
||||
|
||||
var svg = d3.select(element).select('svg');
|
||||
|
||||
var nodes = svg.selectAll("g.node");
|
||||
nodes
|
||||
.on("mouseover", function(d) {
|
||||
var el = d3.select(this);
|
||||
var title = el.attr('title');
|
||||
// Dont try to draw a tooltip if no data is provided
|
||||
if(title === null){
|
||||
return;
|
||||
}
|
||||
var rect = this.getBoundingClientRect();
|
||||
|
||||
tooltipElem.transition()
|
||||
.duration(200)
|
||||
.style("opacity", .9);
|
||||
tooltipElem.html(el.attr('title'))
|
||||
.style("left", (rect.left+(rect.right-rect.left)/2) + "px")
|
||||
.style("top", (rect.top-28) + "px");
|
||||
var el = d3.select(this);
|
||||
el.classed('hover',true);
|
||||
|
||||
})
|
||||
.on("mouseout", function(d) {
|
||||
tooltipElem.transition()
|
||||
.duration(500)
|
||||
.style("opacity", 0);
|
||||
var el = d3.select(this);
|
||||
el.classed('hover',false);
|
||||
});
|
||||
};
|
||||
funs.push(setupToolTips);
|
||||
|
||||
/**
|
||||
* Clears the internal graph db so that a new graph can be parsed.
|
||||
*/
|
||||
@ -214,9 +279,11 @@ exports.clear = function () {
|
||||
vertices = {};
|
||||
classes = {};
|
||||
edges = [];
|
||||
//funs = [];
|
||||
funs = [];
|
||||
funs.push(setupToolTips);
|
||||
subGraphs = [];
|
||||
subCount = 0;
|
||||
tooltips = [];
|
||||
};
|
||||
/**
|
||||
*
|
||||
|
@ -386,8 +386,11 @@ classStatement:CLASS SPACE alphaNum SPACE alphaNum
|
||||
{$$ = $1;yy.setClass($3, $5);}
|
||||
;
|
||||
|
||||
clickStatement:CLICK SPACE alphaNum SPACE alphaNum
|
||||
{$$ = $1;yy.setClickEvent($3, $5);}
|
||||
clickStatement
|
||||
: CLICK SPACE alphaNum SPACE alphaNum {$$ = $1;yy.setClickEvent($3, $5, undefined, undefined);}
|
||||
| CLICK SPACE alphaNum SPACE alphaNum SPACE STR {$$ = $1;yy.setClickEvent($3, $5, undefined, $7) ;}
|
||||
| CLICK SPACE alphaNum SPACE STR {$$ = $1;yy.setClickEvent($3, undefined, $5, undefined);}
|
||||
| CLICK SPACE alphaNum SPACE STR SPACE STR {$$ = $1;yy.setClickEvent($3, undefined, $5, $7 );}
|
||||
;
|
||||
|
||||
styleStatement:STYLE SPACE alphaNum SPACE stylesOpt
|
||||
|
File diff suppressed because one or more lines are too long
@ -431,6 +431,49 @@ describe('when parsing ',function(){
|
||||
expect(edges[0].type).toBe('arrow');
|
||||
});
|
||||
|
||||
ddescribe("it should handle interaction, ",function(){
|
||||
|
||||
it('it should be possible to use click to a callback',function(){
|
||||
spyOn(graph,'setClickEvent');
|
||||
var res = flow.parser.parse('graph TD\nA-->B\nclick A callback');
|
||||
|
||||
var vert = flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(graph.setClickEvent).toHaveBeenCalledWith('A','callback',undefined,undefined);
|
||||
});
|
||||
|
||||
it('it should be possible to use click to a callback with toolip',function(){
|
||||
spyOn(graph,'setClickEvent');
|
||||
var res = flow.parser.parse('graph TD\nA-->B\nclick A callback "tooltip"');
|
||||
|
||||
var vert = flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(graph.setClickEvent).toHaveBeenCalledWith('A','callback',undefined,'tooltip');
|
||||
});
|
||||
|
||||
it('should handle interaction - click to a link',function(){
|
||||
spyOn(graph,'setClickEvent');
|
||||
var res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html"');
|
||||
|
||||
var vert = flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(graph.setClickEvent).toHaveBeenCalledWith('A',undefined,'click.html',undefined);
|
||||
});
|
||||
it('should handle interaction - click to a link with tooltip',function(){
|
||||
spyOn(graph,'setClickEvent');
|
||||
var res = flow.parser.parse('graph TD\nA-->B\nclick A "click.html" "tooltip"');
|
||||
|
||||
var vert = flow.parser.yy.getVertices();
|
||||
var edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(graph.setClickEvent).toHaveBeenCalledWith('A',undefined,'click.html','tooltip');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("it should handle text on edges",function(){
|
||||
it('it should handle text without space',function(){
|
||||
var res = flow.parser.parse('graph TD;A--x|textNoSpace|B;');
|
||||
|
@ -97,11 +97,12 @@ var init = function () {
|
||||
mermaidAPI.initialize({gantt:mermaid.ganttConfig});
|
||||
}
|
||||
|
||||
var insertSvg = function(svgCode){
|
||||
var insertSvg = function(svgCode, bindFunctions){
|
||||
element.innerHTML = svgCode;
|
||||
if(typeof callback !== 'undefined'){
|
||||
callback(id);
|
||||
}
|
||||
bindFunctions(element);
|
||||
};
|
||||
|
||||
for (i = 0; i < nodes.length; i++) {
|
||||
|
@ -323,7 +323,6 @@ var render = function(id, txt, cb, container){
|
||||
classes = flowRenderer.getClasses(txt, false);
|
||||
utils.cloneCssStyles(element.firstChild, classes);
|
||||
}
|
||||
graph.bindFunctions();
|
||||
break;
|
||||
case 'dotGraph':
|
||||
flowRenderer.setConf(config.flowchart);
|
||||
|
81
test/examples/links.html
Normal file
81
test/examples/links.html
Normal file
@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<link rel="stylesheet" href="../../dist/mermaid.css"/>
|
||||
<script src="../../dist/mermaid.js"></script>
|
||||
<link rel="stylesheet" href="../../dist/mermaid.css"/>
|
||||
<style>
|
||||
body{
|
||||
background-color: #2d2d22;
|
||||
}
|
||||
div.mermaidTooltip {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 60px;
|
||||
height: 28px;
|
||||
padding: 2px;
|
||||
font: 12px sans-serif;
|
||||
background: lightsteelblue;
|
||||
border: 1px solid black;
|
||||
border-radius: 3px;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function itsTime(){
|
||||
|
||||
function getScreenCoords(x, y, ctm) {
|
||||
var xn = ctm.e + x*ctm.a;
|
||||
var yn = ctm.f + y*ctm.d;
|
||||
return { x: xn, y: yn };
|
||||
}
|
||||
|
||||
|
||||
setTimeout(function(){
|
||||
|
||||
},250);
|
||||
|
||||
}
|
||||
function callback(id){
|
||||
alert(id);
|
||||
}
|
||||
function callback2(id){
|
||||
alert('x'+id);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="itsTime()">
|
||||
<h1>Links to callbacks</h1>
|
||||
A has a tooltip
|
||||
<div class="mermaid" id="i211">
|
||||
graph LR;
|
||||
A-->B;
|
||||
B-->C;
|
||||
click A callback "Tooltip"
|
||||
click B "http://www.github.com" "This is a link"
|
||||
click C callback "Tooltip C1"
|
||||
</div>
|
||||
|
||||
<h1>Links to urls</h1>
|
||||
<div class="mermaid" id="i213">
|
||||
graph LR;
|
||||
A-->B
|
||||
B-->C
|
||||
click A callback2 "Tooltip3"
|
||||
</div>
|
||||
<div class="mermaid" id="i213">
|
||||
graph LR;
|
||||
subgraph S1
|
||||
a-->b
|
||||
end
|
||||
subgraph S2
|
||||
c-->d
|
||||
c-->d
|
||||
end
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user