2017-09-10 19:41:34 +08:00
|
|
|
import { logger } from '../../logger'
|
|
|
|
import utils from '../../utils'
|
|
|
|
import d3 from '../../d3'
|
2017-04-11 22:14:25 +08:00
|
|
|
|
|
|
|
var vertices = {}
|
|
|
|
var edges = []
|
|
|
|
var classes = []
|
|
|
|
var subGraphs = []
|
|
|
|
var tooltips = {}
|
|
|
|
var subCount = 0
|
|
|
|
var direction
|
2014-11-24 22:03:32 +01:00
|
|
|
// Functions to be run after graph rendering
|
2017-04-11 22:14:25 +08:00
|
|
|
var funs = []
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
* Function called by parser when a node definition has been found
|
|
|
|
* @param id
|
|
|
|
* @param text
|
|
|
|
* @param type
|
|
|
|
* @param style
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const addVertex = function (id, text, type, style) {
|
2017-04-11 22:14:25 +08:00
|
|
|
var txt
|
2014-12-04 17:58:05 +01:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (typeof id === 'undefined') {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (id.trim().length === 0) {
|
|
|
|
return
|
|
|
|
}
|
2015-05-29 08:23:13 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (typeof vertices[id] === 'undefined') {
|
2017-04-16 23:48:36 +08:00
|
|
|
vertices[id] = { id: id, styles: [], classes: [] }
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
if (typeof text !== 'undefined') {
|
|
|
|
txt = text.trim()
|
|
|
|
|
2017-04-16 23:48:36 +08:00
|
|
|
// strip quotes if string starts and exnds with a quote
|
2017-04-11 22:14:25 +08:00
|
|
|
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
|
|
|
|
txt = txt.substring(1, txt.length - 1)
|
2014-11-22 15:34:21 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
|
|
|
|
vertices[id].text = txt
|
|
|
|
}
|
|
|
|
if (typeof type !== 'undefined') {
|
|
|
|
vertices[id].type = type
|
|
|
|
}
|
|
|
|
if (typeof type !== 'undefined') {
|
|
|
|
vertices[id].type = type
|
|
|
|
}
|
|
|
|
if (typeof style !== 'undefined') {
|
|
|
|
if (style !== null) {
|
|
|
|
style.forEach(function (s) {
|
|
|
|
vertices[id].styles.push(s)
|
|
|
|
})
|
2014-11-20 20:46:51 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
}
|
2014-12-04 17:58:05 +01:00
|
|
|
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
* Function called by parser when a link/edge definition has been found
|
|
|
|
* @param start
|
|
|
|
* @param end
|
|
|
|
* @param type
|
|
|
|
* @param linktext
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const addLink = function (start, end, type, linktext) {
|
2017-09-10 19:41:34 +08:00
|
|
|
logger.info('Got edge...', start, end)
|
2017-04-16 23:48:36 +08:00
|
|
|
var edge = { start: start, end: end, type: undefined, text: '' }
|
2017-04-11 22:14:25 +08:00
|
|
|
linktext = type.text
|
|
|
|
|
|
|
|
if (typeof linktext !== 'undefined') {
|
|
|
|
edge.text = linktext.trim()
|
2014-12-09 22:26:42 -08:00
|
|
|
|
2017-04-16 23:48:36 +08:00
|
|
|
// strip quotes if string starts and exnds with a quote
|
2017-04-11 22:14:25 +08:00
|
|
|
if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') {
|
|
|
|
edge.text = edge.text.substring(1, edge.text.length - 1)
|
2014-11-20 20:46:51 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2014-11-20 20:46:51 +01:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (typeof type !== 'undefined') {
|
|
|
|
edge.type = type.type
|
|
|
|
edge.stroke = type.stroke
|
|
|
|
}
|
|
|
|
edges.push(edge)
|
|
|
|
}
|
2016-04-28 20:59:09 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates a link's line interpolation algorithm
|
|
|
|
* @param pos
|
|
|
|
* @param interpolate
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const updateLinkInterpolate = function (pos, interp) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (pos === 'default') {
|
|
|
|
edges.defaultInterpolate = interp
|
|
|
|
} else {
|
|
|
|
edges[pos].interpolate = interp
|
|
|
|
}
|
|
|
|
}
|
2016-04-28 20:59:09 -04:00
|
|
|
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
* Updates a link with a style
|
|
|
|
* @param pos
|
|
|
|
* @param style
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const updateLink = function (pos, style) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (pos === 'default') {
|
|
|
|
edges.defaultStyle = style
|
|
|
|
} else {
|
|
|
|
if (utils.isSubstringInArray('fill', style) === -1) {
|
|
|
|
style.push('fill:none')
|
2015-02-28 23:50:23 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
edges[pos].style = style
|
|
|
|
}
|
|
|
|
}
|
2014-11-22 15:34:21 +01:00
|
|
|
|
2017-09-10 21:23:04 +08:00
|
|
|
export const addClass = function (id, style) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (typeof classes[id] === 'undefined') {
|
2017-04-16 23:48:36 +08:00
|
|
|
classes[id] = { id: id, styles: [] }
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof style !== 'undefined') {
|
|
|
|
if (style !== null) {
|
|
|
|
style.forEach(function (s) {
|
|
|
|
classes[id].styles.push(s)
|
|
|
|
})
|
2014-11-22 15:34:21 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
}
|
2014-11-22 15:34:21 +01:00
|
|
|
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
* Called by parser when a graph definition is found, stores the direction of the chart.
|
|
|
|
* @param dir
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const setDirection = function (dir) {
|
2017-04-11 22:14:25 +08:00
|
|
|
direction = dir
|
|
|
|
}
|
2014-11-22 15:34:21 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by parser when a graph definition is found, stores the direction of the chart.
|
|
|
|
* @param dir
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const setClass = function (id, className) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (id.indexOf(',') > 0) {
|
|
|
|
id.split(',').forEach(function (id2) {
|
|
|
|
if (typeof vertices[id2] !== 'undefined') {
|
|
|
|
vertices[id2].classes.push(className)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
} else {
|
2015-10-02 00:18:47 +02:00
|
|
|
if (typeof vertices[id] !== 'undefined') {
|
2017-04-11 22:14:25 +08:00
|
|
|
vertices[id].classes.push(className)
|
2015-10-02 00:18:47 +02:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 () {
|
2017-04-13 20:16:38 +08:00
|
|
|
window[functionName](id)
|
2017-04-11 22:14:25 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 () {
|
2017-04-21 11:21:42 +08:00
|
|
|
window.open(linkStr, 'newTab')
|
2017-04-11 22:14:25 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getTooltip = function (id) {
|
2017-04-11 22:14:25 +08:00
|
|
|
return tooltips[id]
|
|
|
|
}
|
2015-10-17 12:46:36 +02:00
|
|
|
|
2014-11-24 22:03:32 +01:00
|
|
|
/**
|
|
|
|
* Called by parser when a graph definition is found, stores the direction of the chart.
|
|
|
|
* @param dir
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const setClickEvent = function (id, functionName, link, tooltip) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (id.indexOf(',') > 0) {
|
|
|
|
id.split(',').forEach(function (id2) {
|
|
|
|
setTooltip(id2, tooltip)
|
|
|
|
setClickFun(id2, functionName)
|
|
|
|
setLink(id2, link)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
setTooltip(id, tooltip)
|
|
|
|
setClickFun(id, functionName)
|
|
|
|
setLink(id, link)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-10 21:23:04 +08:00
|
|
|
export const bindFunctions = function (element) {
|
2017-04-11 22:14:25 +08:00
|
|
|
funs.forEach(function (fun) {
|
|
|
|
fun(element)
|
|
|
|
})
|
|
|
|
}
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getDirection = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
return direction
|
|
|
|
}
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
* Retrieval function for fetching the found nodes after parsing has completed.
|
|
|
|
* @returns {{}|*|vertices}
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getVertices = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
return vertices
|
|
|
|
}
|
2014-11-20 20:46:51 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieval function for fetching the found links after parsing has completed.
|
|
|
|
* @returns {{}|*|edges}
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getEdges = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
return edges
|
|
|
|
}
|
2014-11-20 20:46:51 +01:00
|
|
|
|
2014-11-22 15:34:21 +01:00
|
|
|
/**
|
|
|
|
* Retrieval function for fetching the found class definitions after parsing has completed.
|
|
|
|
* @returns {{}|*|classes}
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getClasses = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
return classes
|
|
|
|
}
|
2014-11-22 15:34:21 +01:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
var setupToolTips = function (element) {
|
|
|
|
var tooltipElem = d3.select('.mermaidTooltip')
|
|
|
|
if (tooltipElem[0][0] === null) {
|
|
|
|
tooltipElem = d3.select('body')
|
2017-04-16 23:48:36 +08:00
|
|
|
.append('div')
|
|
|
|
.attr('class', 'mermaidTooltip')
|
|
|
|
.style('opacity', 0)
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2015-10-02 00:18:47 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
var svg = d3.select(element).select('svg')
|
2015-10-02 00:18:47 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
var nodes = svg.selectAll('g.node')
|
|
|
|
nodes
|
2017-04-16 23:48:36 +08:00
|
|
|
.on('mouseover', function () {
|
|
|
|
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 - 14 + document.body.scrollTop) + 'px')
|
|
|
|
el.classed('hover', true)
|
|
|
|
})
|
|
|
|
.on('mouseout', function () {
|
|
|
|
tooltipElem.transition()
|
|
|
|
.duration(500)
|
|
|
|
.style('opacity', 0)
|
|
|
|
var el = d3.select(this)
|
|
|
|
el.classed('hover', false)
|
|
|
|
})
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
funs.push(setupToolTips)
|
2015-10-02 00:18:47 +02:00
|
|
|
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
* Clears the internal graph db so that a new graph can be parsed.
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const clear = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
vertices = {}
|
|
|
|
classes = {}
|
|
|
|
edges = []
|
|
|
|
funs = []
|
|
|
|
funs.push(setupToolTips)
|
|
|
|
subGraphs = []
|
|
|
|
subCount = 0
|
|
|
|
tooltips = []
|
|
|
|
}
|
2014-11-20 20:46:51 +01:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const defaultStyle = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
return 'fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;'
|
|
|
|
}
|
2015-01-07 21:02:58 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the internal graph db so that a new graph can be parsed.
|
|
|
|
*/
|
2017-09-10 21:23:04 +08:00
|
|
|
export const addSubGraph = function (list, title) {
|
2017-04-11 22:14:25 +08:00
|
|
|
function uniq (a) {
|
2017-04-16 23:48:36 +08:00
|
|
|
var prims = { 'boolean': {}, 'number': {}, 'string': {} }
|
2017-04-13 20:16:38 +08:00
|
|
|
var objs = []
|
2017-04-11 22:14:25 +08:00
|
|
|
|
|
|
|
return a.filter(function (item) {
|
|
|
|
var type = typeof item
|
|
|
|
if (item === ' ') {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if (type in prims) { return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true) } else { return objs.indexOf(item) >= 0 ? false : objs.push(item) }
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
var nodeList = []
|
|
|
|
|
|
|
|
nodeList = uniq(nodeList.concat.apply(nodeList, list))
|
|
|
|
|
2017-04-16 23:48:36 +08:00
|
|
|
var subGraph = { id: 'subGraph' + subCount, nodes: nodeList, title: title }
|
2017-04-11 22:14:25 +08:00
|
|
|
subGraphs.push(subGraph)
|
|
|
|
subCount = subCount + 1
|
|
|
|
return subGraph.id
|
|
|
|
}
|
|
|
|
|
|
|
|
var getPosForId = function (id) {
|
|
|
|
var i
|
|
|
|
for (i = 0; i < subGraphs.length; i++) {
|
|
|
|
if (subGraphs[i].id === id) {
|
|
|
|
return i
|
2015-05-26 20:41:53 +02:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
var secCount = -1
|
|
|
|
var posCrossRef = []
|
2017-09-10 21:23:04 +08:00
|
|
|
var indexNodes2 = function (id, pos) {
|
2017-04-11 22:14:25 +08:00
|
|
|
var nodes = subGraphs[pos].nodes
|
|
|
|
secCount = secCount + 1
|
|
|
|
if (secCount > 2000) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
posCrossRef[secCount] = pos
|
2017-04-16 23:48:36 +08:00
|
|
|
// Check if match
|
2017-04-11 22:14:25 +08:00
|
|
|
if (subGraphs[pos].id === id) {
|
|
|
|
return {
|
|
|
|
result: true,
|
|
|
|
count: 0
|
2015-05-26 20:41:53 +02:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2015-05-26 20:41:53 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
var count = 0
|
|
|
|
var posCount = 1
|
|
|
|
while (count < nodes.length) {
|
|
|
|
var childPos = getPosForId(nodes[count])
|
2017-04-16 23:48:36 +08:00
|
|
|
// Ignore regular nodes (pos will be -1)
|
2017-04-11 22:14:25 +08:00
|
|
|
if (childPos >= 0) {
|
2017-09-10 21:23:04 +08:00
|
|
|
var res = indexNodes2(id, childPos)
|
2017-04-11 22:14:25 +08:00
|
|
|
if (res.result) {
|
|
|
|
return {
|
|
|
|
result: true,
|
|
|
|
count: posCount + res.count
|
2015-05-26 20:41:53 +02:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
} else {
|
|
|
|
posCount = posCount + res.count
|
|
|
|
}
|
2015-05-26 20:41:53 +02:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
count = count + 1
|
|
|
|
}
|
2015-05-26 20:41:53 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
return {
|
|
|
|
result: false,
|
|
|
|
count: posCount
|
|
|
|
}
|
|
|
|
}
|
2015-05-26 20:41:53 +02:00
|
|
|
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getDepthFirstPos = function (pos) {
|
2017-04-11 22:14:25 +08:00
|
|
|
return posCrossRef[pos]
|
|
|
|
}
|
2017-09-10 21:23:04 +08:00
|
|
|
export const indexNodes = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
secCount = -1
|
|
|
|
if (subGraphs.length > 0) {
|
2017-09-10 21:23:04 +08:00
|
|
|
indexNodes2('none', subGraphs.length - 1, 0)
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
}
|
2015-05-26 20:41:53 +02:00
|
|
|
|
2017-09-10 21:23:04 +08:00
|
|
|
export const getSubGraphs = function () {
|
2017-04-11 22:14:25 +08:00
|
|
|
return subGraphs
|
|
|
|
}
|