add lisp packages
This commit is contained in:
Generated
Vendored
+1247
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+117
@@ -0,0 +1,117 @@
|
||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.dagreD3=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){
|
||||
/**
|
||||
* @license
|
||||
* Copyright (c) 2012-2013 Chris Pettitt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
module.exports={graphlib:require("./lib/graphlib"),dagre:require("./lib/dagre"),intersect:require("./lib/intersect"),render:require("./lib/render"),util:require("./lib/util"),version:require("./lib/version")}},{"./lib/dagre":8,"./lib/graphlib":9,"./lib/intersect":10,"./lib/render":25,"./lib/util":27,"./lib/version":28}],2:[function(require,module,exports){var util=require("./util");module.exports={default:normal,normal:normal,vee:vee,undirected:undirected};function normal(parent,id,edge,type){var marker=parent.append("marker").attr("id",id).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto");var path=marker.append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("stroke-width",1).style("stroke-dasharray","1,0");util.applyStyle(path,edge[type+"Style"]);if(edge[type+"Class"]){path.attr("class",edge[type+"Class"])}}function vee(parent,id,edge,type){var marker=parent.append("marker").attr("id",id).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto");var path=marker.append("path").attr("d","M 0 0 L 10 5 L 0 10 L 4 5 z").style("stroke-width",1).style("stroke-dasharray","1,0");util.applyStyle(path,edge[type+"Style"]);if(edge[type+"Class"]){path.attr("class",edge[type+"Class"])}}function undirected(parent,id,edge,type){var marker=parent.append("marker").attr("id",id).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto");var path=marker.append("path").attr("d","M 0 5 L 10 5").style("stroke-width",1).style("stroke-dasharray","1,0");util.applyStyle(path,edge[type+"Style"]);if(edge[type+"Class"]){path.attr("class",edge[type+"Class"])}}},{"./util":27}],3:[function(require,module,exports){var util=require("./util");var d3=require("./d3");var addLabel=require("./label/add-label");module.exports=createClusters;function createClusters(selection,g){var clusters=g.nodes().filter(function(v){return util.isSubgraph(g,v)});var svgClusters=selection.selectAll("g.cluster").data(clusters,function(v){return v});svgClusters.selectAll("*").remove();svgClusters.enter().append("g").attr("class","cluster").attr("id",function(v){var node=g.node(v);return node.id}).style("opacity",0);svgClusters=selection.selectAll("g.cluster");util.applyTransition(svgClusters,g).style("opacity",1);svgClusters.each(function(v){var node=g.node(v);var thisGroup=d3.select(this);d3.select(this).append("rect");var labelGroup=thisGroup.append("g").attr("class","label");addLabel(labelGroup,node,node.clusterLabelPos)});svgClusters.selectAll("rect").each(function(c){var node=g.node(c);var domCluster=d3.select(this);util.applyStyle(domCluster,node.style)});var exitSelection;if(svgClusters.exit){exitSelection=svgClusters.exit()}else{exitSelection=svgClusters.selectAll(null);// empty selection
|
||||
}util.applyTransition(exitSelection,g).style("opacity",0).remove();return svgClusters}},{"./d3":7,"./label/add-label":18,"./util":27}],4:[function(require,module,exports){"use strict";var _=require("./lodash");var addLabel=require("./label/add-label");var util=require("./util");var d3=require("./d3");module.exports=createEdgeLabels;function createEdgeLabels(selection,g){var svgEdgeLabels=selection.selectAll("g.edgeLabel").data(g.edges(),function(e){return util.edgeToId(e)}).classed("update",true);svgEdgeLabels.exit().remove();svgEdgeLabels.enter().append("g").classed("edgeLabel",true).style("opacity",0);svgEdgeLabels=selection.selectAll("g.edgeLabel");svgEdgeLabels.each(function(e){var root=d3.select(this);root.select(".label").remove();var edge=g.edge(e);var label=addLabel(root,g.edge(e),0,0).classed("label",true);var bbox=label.node().getBBox();if(edge.labelId){label.attr("id",edge.labelId)}if(!_.has(edge,"width")){edge.width=bbox.width}if(!_.has(edge,"height")){edge.height=bbox.height}});var exitSelection;if(svgEdgeLabels.exit){exitSelection=svgEdgeLabels.exit()}else{exitSelection=svgEdgeLabels.selectAll(null);// empty selection
|
||||
}util.applyTransition(exitSelection,g).style("opacity",0).remove();return svgEdgeLabels}},{"./d3":7,"./label/add-label":18,"./lodash":21,"./util":27}],5:[function(require,module,exports){"use strict";var _=require("./lodash");var intersectNode=require("./intersect/intersect-node");var util=require("./util");var d3=require("./d3");module.exports=createEdgePaths;function createEdgePaths(selection,g,arrows){var previousPaths=selection.selectAll("g.edgePath").data(g.edges(),function(e){return util.edgeToId(e)}).classed("update",true);var newPaths=enter(previousPaths,g);exit(previousPaths,g);var svgPaths=previousPaths.merge!==undefined?previousPaths.merge(newPaths):previousPaths;util.applyTransition(svgPaths,g).style("opacity",1);
|
||||
// Save DOM element in the path group, and set ID and class
|
||||
svgPaths.each(function(e){var domEdge=d3.select(this);var edge=g.edge(e);edge.elem=this;if(edge.id){domEdge.attr("id",edge.id)}util.applyClass(domEdge,edge["class"],(domEdge.classed("update")?"update ":"")+"edgePath")});svgPaths.selectAll("path.path").each(function(e){var edge=g.edge(e);edge.arrowheadId=_.uniqueId("arrowhead");var domEdge=d3.select(this).attr("marker-end",function(){return"url("+makeFragmentRef(location.href,edge.arrowheadId)+")"}).style("fill","none");util.applyTransition(domEdge,g).attr("d",function(e){return calcPoints(g,e)});util.applyStyle(domEdge,edge.style)});svgPaths.selectAll("defs *").remove();svgPaths.selectAll("defs").each(function(e){var edge=g.edge(e);var arrowhead=arrows[edge.arrowhead];arrowhead(d3.select(this),edge.arrowheadId,edge,"arrowhead")});return svgPaths}function makeFragmentRef(url,fragmentId){var baseUrl=url.split("#")[0];return baseUrl+"#"+fragmentId}function calcPoints(g,e){var edge=g.edge(e);var tail=g.node(e.v);var head=g.node(e.w);var points=edge.points.slice(1,edge.points.length-1);points.unshift(intersectNode(tail,points[0]));points.push(intersectNode(head,points[points.length-1]));return createLine(edge,points)}function createLine(edge,points){var line=(d3.line||d3.svg.line)().x(function(d){return d.x}).y(function(d){return d.y});(line.curve||line.interpolate)(edge.curve);return line(points)}function getCoords(elem){var bbox=elem.getBBox();var matrix=elem.ownerSVGElement.getScreenCTM().inverse().multiply(elem.getScreenCTM()).translate(bbox.width/2,bbox.height/2);return{x:matrix.e,y:matrix.f}}function enter(svgPaths,g){var svgPathsEnter=svgPaths.enter().append("g").attr("class","edgePath").style("opacity",0);svgPathsEnter.append("path").attr("class","path").attr("d",function(e){var edge=g.edge(e);var sourceElem=g.node(e.v).elem;var points=_.range(edge.points.length).map(function(){return getCoords(sourceElem)});return createLine(edge,points)});svgPathsEnter.append("defs");return svgPathsEnter}function exit(svgPaths,g){var svgPathExit=svgPaths.exit();util.applyTransition(svgPathExit,g).style("opacity",0).remove()}},{"./d3":7,"./intersect/intersect-node":14,"./lodash":21,"./util":27}],6:[function(require,module,exports){"use strict";var _=require("./lodash");var addLabel=require("./label/add-label");var util=require("./util");var d3=require("./d3");module.exports=createNodes;function createNodes(selection,g,shapes){var simpleNodes=g.nodes().filter(function(v){return!util.isSubgraph(g,v)});var svgNodes=selection.selectAll("g.node").data(simpleNodes,function(v){return v}).classed("update",true);svgNodes.exit().remove();svgNodes.enter().append("g").attr("class","node").style("opacity",0);svgNodes=selection.selectAll("g.node");svgNodes.each(function(v){var node=g.node(v);var thisGroup=d3.select(this);util.applyClass(thisGroup,node["class"],(thisGroup.classed("update")?"update ":"")+"node");thisGroup.select("g.label").remove();var labelGroup=thisGroup.append("g").attr("class","label");var labelDom=addLabel(labelGroup,node);var shape=shapes[node.shape];var bbox=_.pick(labelDom.node().getBBox(),"width","height");node.elem=this;if(node.id){thisGroup.attr("id",node.id)}if(node.labelId){labelGroup.attr("id",node.labelId)}if(_.has(node,"width")){bbox.width=node.width}if(_.has(node,"height")){bbox.height=node.height}bbox.width+=node.paddingLeft+node.paddingRight;bbox.height+=node.paddingTop+node.paddingBottom;labelGroup.attr("transform","translate("+(node.paddingLeft-node.paddingRight)/2+","+(node.paddingTop-node.paddingBottom)/2+")");var root=d3.select(this);root.select(".label-container").remove();var shapeSvg=shape(root,bbox,node).classed("label-container",true);util.applyStyle(shapeSvg,node.style);var shapeBBox=shapeSvg.node().getBBox();node.width=shapeBBox.width;node.height=shapeBBox.height});var exitSelection;if(svgNodes.exit){exitSelection=svgNodes.exit()}else{exitSelection=svgNodes.selectAll(null);// empty selection
|
||||
}util.applyTransition(exitSelection,g).style("opacity",0).remove();return svgNodes}},{"./d3":7,"./label/add-label":18,"./lodash":21,"./util":27}],7:[function(require,module,exports){
|
||||
// Stub to get D3 either via NPM or from the global object
|
||||
var d3;if(!d3){if(typeof require==="function"){try{d3=require("d3")}catch(e){
|
||||
// continue regardless of error
|
||||
}}}if(!d3){d3=window.d3}module.exports=d3},{d3:undefined}],8:[function(require,module,exports){
|
||||
/* global window */
|
||||
var dagre;if(typeof require==="function"){try{dagre=require("dagre")}catch(e){
|
||||
// continue regardless of error
|
||||
}}if(!dagre){dagre=window.dagre}module.exports=dagre},{dagre:undefined}],9:[function(require,module,exports){
|
||||
/* global window */
|
||||
var graphlib;if(typeof require==="function"){try{graphlib=require("graphlib")}catch(e){
|
||||
// continue regardless of error
|
||||
}}if(!graphlib){graphlib=window.graphlib}module.exports=graphlib},{graphlib:undefined}],10:[function(require,module,exports){module.exports={node:require("./intersect-node"),circle:require("./intersect-circle"),ellipse:require("./intersect-ellipse"),polygon:require("./intersect-polygon"),rect:require("./intersect-rect")}},{"./intersect-circle":11,"./intersect-ellipse":12,"./intersect-node":14,"./intersect-polygon":15,"./intersect-rect":16}],11:[function(require,module,exports){var intersectEllipse=require("./intersect-ellipse");module.exports=intersectCircle;function intersectCircle(node,rx,point){return intersectEllipse(node,rx,rx,point)}},{"./intersect-ellipse":12}],12:[function(require,module,exports){module.exports=intersectEllipse;function intersectEllipse(node,rx,ry,point){
|
||||
// Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html
|
||||
var cx=node.x;var cy=node.y;var px=cx-point.x;var py=cy-point.y;var det=Math.sqrt(rx*rx*py*py+ry*ry*px*px);var dx=Math.abs(rx*ry*px/det);if(point.x<cx){dx=-dx}var dy=Math.abs(rx*ry*py/det);if(point.y<cy){dy=-dy}return{x:cx+dx,y:cy+dy}}},{}],13:[function(require,module,exports){module.exports=intersectLine;
|
||||
/*
|
||||
* Returns the point at which two lines, p and q, intersect or returns
|
||||
* undefined if they do not intersect.
|
||||
*/function intersectLine(p1,p2,q1,q2){
|
||||
// Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994,
|
||||
// p7 and p473.
|
||||
var a1,a2,b1,b2,c1,c2;var r1,r2,r3,r4;var denom,offset,num;var x,y;
|
||||
// Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x +
|
||||
// b1 y + c1 = 0.
|
||||
a1=p2.y-p1.y;b1=p1.x-p2.x;c1=p2.x*p1.y-p1.x*p2.y;
|
||||
// Compute r3 and r4.
|
||||
r3=a1*q1.x+b1*q1.y+c1;r4=a1*q2.x+b1*q2.y+c1;
|
||||
// Check signs of r3 and r4. If both point 3 and point 4 lie on
|
||||
// same side of line 1, the line segments do not intersect.
|
||||
if(r3!==0&&r4!==0&&sameSign(r3,r4)){return}
|
||||
// Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0
|
||||
a2=q2.y-q1.y;b2=q1.x-q2.x;c2=q2.x*q1.y-q1.x*q2.y;
|
||||
// Compute r1 and r2
|
||||
r1=a2*p1.x+b2*p1.y+c2;r2=a2*p2.x+b2*p2.y+c2;
|
||||
// Check signs of r1 and r2. If both point 1 and point 2 lie
|
||||
// on same side of second line segment, the line segments do
|
||||
// not intersect.
|
||||
if(r1!==0&&r2!==0&&sameSign(r1,r2)){return}
|
||||
// Line segments intersect: compute intersection point.
|
||||
denom=a1*b2-a2*b1;if(denom===0){return}offset=Math.abs(denom/2);
|
||||
// The denom/2 is to get rounding instead of truncating. It
|
||||
// is added or subtracted to the numerator, depending upon the
|
||||
// sign of the numerator.
|
||||
num=b1*c2-b2*c1;x=num<0?(num-offset)/denom:(num+offset)/denom;num=a2*c1-a1*c2;y=num<0?(num-offset)/denom:(num+offset)/denom;return{x:x,y:y}}function sameSign(r1,r2){return r1*r2>0}},{}],14:[function(require,module,exports){module.exports=intersectNode;function intersectNode(node,point){return node.intersect(point)}},{}],15:[function(require,module,exports){
|
||||
/* eslint "no-console": off */
|
||||
var intersectLine=require("./intersect-line");module.exports=intersectPolygon;
|
||||
/*
|
||||
* Returns the point ({x, y}) at which the point argument intersects with the
|
||||
* node argument assuming that it has the shape specified by polygon.
|
||||
*/function intersectPolygon(node,polyPoints,point){var x1=node.x;var y1=node.y;var intersections=[];var minX=Number.POSITIVE_INFINITY;var minY=Number.POSITIVE_INFINITY;polyPoints.forEach(function(entry){minX=Math.min(minX,entry.x);minY=Math.min(minY,entry.y)});var left=x1-node.width/2-minX;var top=y1-node.height/2-minY;for(var i=0;i<polyPoints.length;i++){var p1=polyPoints[i];var p2=polyPoints[i<polyPoints.length-1?i+1:0];var intersect=intersectLine(node,point,{x:left+p1.x,y:top+p1.y},{x:left+p2.x,y:top+p2.y});if(intersect){intersections.push(intersect)}}if(!intersections.length){console.log("NO INTERSECTION FOUND, RETURN NODE CENTER",node);return node}if(intersections.length>1){
|
||||
// More intersections, find the one nearest to edge end point
|
||||
intersections.sort(function(p,q){var pdx=p.x-point.x;var pdy=p.y-point.y;var distp=Math.sqrt(pdx*pdx+pdy*pdy);var qdx=q.x-point.x;var qdy=q.y-point.y;var distq=Math.sqrt(qdx*qdx+qdy*qdy);return distp<distq?-1:distp===distq?0:1})}return intersections[0]}},{"./intersect-line":13}],16:[function(require,module,exports){module.exports=intersectRect;function intersectRect(node,point){var x=node.x;var y=node.y;
|
||||
// Rectangle intersection algorithm from:
|
||||
// http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
|
||||
var dx=point.x-x;var dy=point.y-y;var w=node.width/2;var h=node.height/2;var sx,sy;if(Math.abs(dy)*w>Math.abs(dx)*h){
|
||||
// Intersection is top or bottom of rect.
|
||||
if(dy<0){h=-h}sx=dy===0?0:h*dx/dy;sy=h}else{
|
||||
// Intersection is left or right of rect.
|
||||
if(dx<0){w=-w}sx=w;sy=dx===0?0:w*dy/dx}return{x:x+sx,y:y+sy}}},{}],17:[function(require,module,exports){var util=require("../util");module.exports=addHtmlLabel;function addHtmlLabel(root,node){var fo=root.append("foreignObject").attr("width","100000");var div=fo.append("xhtml:div");div.attr("xmlns","http://www.w3.org/1999/xhtml");var label=node.label;switch(typeof label){case"function":div.insert(label);break;case"object":
|
||||
// Currently we assume this is a DOM object.
|
||||
div.insert(function(){return label});break;default:div.html(label)}util.applyStyle(div,node.labelStyle);div.style("display","inline-block");
|
||||
// Fix for firefox
|
||||
div.style("white-space","nowrap");var client=div.node().getBoundingClientRect();fo.attr("width",client.width).attr("height",client.height);return fo}},{"../util":27}],18:[function(require,module,exports){var addTextLabel=require("./add-text-label");var addHtmlLabel=require("./add-html-label");var addSVGLabel=require("./add-svg-label");module.exports=addLabel;function addLabel(root,node,location){var label=node.label;var labelSvg=root.append("g");
|
||||
// Allow the label to be a string, a function that returns a DOM element, or
|
||||
// a DOM element itself.
|
||||
if(node.labelType==="svg"){addSVGLabel(labelSvg,node)}else if(typeof label!=="string"||node.labelType==="html"){addHtmlLabel(labelSvg,node)}else{addTextLabel(labelSvg,node)}var labelBBox=labelSvg.node().getBBox();var y;switch(location){case"top":y=-node.height/2;break;case"bottom":y=node.height/2-labelBBox.height;break;default:y=-labelBBox.height/2}labelSvg.attr("transform","translate("+-labelBBox.width/2+","+y+")");return labelSvg}},{"./add-html-label":17,"./add-svg-label":19,"./add-text-label":20}],19:[function(require,module,exports){var util=require("../util");module.exports=addSVGLabel;function addSVGLabel(root,node){var domNode=root;domNode.node().appendChild(node.label);util.applyStyle(domNode,node.labelStyle);return domNode}},{"../util":27}],20:[function(require,module,exports){var util=require("../util");module.exports=addTextLabel;
|
||||
/*
|
||||
* Attaches a text label to the specified root. Handles escape sequences.
|
||||
*/function addTextLabel(root,node){var domNode=root.append("text");var lines=processEscapeSequences(node.label).split("\n");for(var i=0;i<lines.length;i++){domNode.append("tspan").attr("xml:space","preserve").attr("dy","1em").attr("x","1").text(lines[i])}util.applyStyle(domNode,node.labelStyle);return domNode}function processEscapeSequences(text){var newText="";var escaped=false;var ch;for(var i=0;i<text.length;++i){ch=text[i];if(escaped){switch(ch){case"n":newText+="\n";break;default:newText+=ch}escaped=false}else if(ch==="\\"){escaped=true}else{newText+=ch}}return newText}},{"../util":27}],21:[function(require,module,exports){
|
||||
/* global window */
|
||||
var lodash;if(typeof require==="function"){try{lodash={defaults:require("lodash/defaults"),each:require("lodash/each"),isFunction:require("lodash/isFunction"),isPlainObject:require("lodash/isPlainObject"),pick:require("lodash/pick"),has:require("lodash/has"),range:require("lodash/range"),uniqueId:require("lodash/uniqueId")}}catch(e){
|
||||
// continue regardless of error
|
||||
}}if(!lodash){lodash=window._}module.exports=lodash},{"lodash/defaults":undefined,"lodash/each":undefined,"lodash/has":undefined,"lodash/isFunction":undefined,"lodash/isPlainObject":undefined,"lodash/pick":undefined,"lodash/range":undefined,"lodash/uniqueId":undefined}],22:[function(require,module,exports){"use strict";var util=require("./util");var d3=require("./d3");module.exports=positionClusters;function positionClusters(selection,g){var created=selection.filter(function(){return!d3.select(this).classed("update")});function translate(v){var node=g.node(v);return"translate("+node.x+","+node.y+")"}created.attr("transform",translate);util.applyTransition(selection,g).style("opacity",1).attr("transform",translate);util.applyTransition(created.selectAll("rect"),g).attr("width",function(v){return g.node(v).width}).attr("height",function(v){return g.node(v).height}).attr("x",function(v){var node=g.node(v);return-node.width/2}).attr("y",function(v){var node=g.node(v);return-node.height/2})}},{"./d3":7,"./util":27}],23:[function(require,module,exports){"use strict";var util=require("./util");var d3=require("./d3");var _=require("./lodash");module.exports=positionEdgeLabels;function positionEdgeLabels(selection,g){var created=selection.filter(function(){return!d3.select(this).classed("update")});function translate(e){var edge=g.edge(e);return _.has(edge,"x")?"translate("+edge.x+","+edge.y+")":""}created.attr("transform",translate);util.applyTransition(selection,g).style("opacity",1).attr("transform",translate)}},{"./d3":7,"./lodash":21,"./util":27}],24:[function(require,module,exports){"use strict";var util=require("./util");var d3=require("./d3");module.exports=positionNodes;function positionNodes(selection,g){var created=selection.filter(function(){return!d3.select(this).classed("update")});function translate(v){var node=g.node(v);return"translate("+node.x+","+node.y+")"}created.attr("transform",translate);util.applyTransition(selection,g).style("opacity",1).attr("transform",translate)}},{"./d3":7,"./util":27}],25:[function(require,module,exports){var _=require("./lodash");var d3=require("./d3");var layout=require("./dagre").layout;module.exports=render;
|
||||
// This design is based on http://bost.ocks.org/mike/chart/.
|
||||
function render(){var createNodes=require("./create-nodes");var createClusters=require("./create-clusters");var createEdgeLabels=require("./create-edge-labels");var createEdgePaths=require("./create-edge-paths");var positionNodes=require("./position-nodes");var positionEdgeLabels=require("./position-edge-labels");var positionClusters=require("./position-clusters");var shapes=require("./shapes");var arrows=require("./arrows");var fn=function(svg,g){preProcessGraph(g);var outputGroup=createOrSelectGroup(svg,"output");var clustersGroup=createOrSelectGroup(outputGroup,"clusters");var edgePathsGroup=createOrSelectGroup(outputGroup,"edgePaths");var edgeLabels=createEdgeLabels(createOrSelectGroup(outputGroup,"edgeLabels"),g);var nodes=createNodes(createOrSelectGroup(outputGroup,"nodes"),g,shapes);layout(g);positionNodes(nodes,g);positionEdgeLabels(edgeLabels,g);createEdgePaths(edgePathsGroup,g,arrows);var clusters=createClusters(clustersGroup,g);positionClusters(clusters,g);postProcessGraph(g)};fn.createNodes=function(value){if(!arguments.length)return createNodes;createNodes=value;return fn};fn.createClusters=function(value){if(!arguments.length)return createClusters;createClusters=value;return fn};fn.createEdgeLabels=function(value){if(!arguments.length)return createEdgeLabels;createEdgeLabels=value;return fn};fn.createEdgePaths=function(value){if(!arguments.length)return createEdgePaths;createEdgePaths=value;return fn};fn.shapes=function(value){if(!arguments.length)return shapes;shapes=value;return fn};fn.arrows=function(value){if(!arguments.length)return arrows;arrows=value;return fn};return fn}var NODE_DEFAULT_ATTRS={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"};var EDGE_DEFAULT_ATTRS={arrowhead:"normal",curve:d3.curveLinear};function preProcessGraph(g){g.nodes().forEach(function(v){var node=g.node(v);if(!_.has(node,"label")&&!g.children(v).length){node.label=v}if(_.has(node,"paddingX")){_.defaults(node,{paddingLeft:node.paddingX,paddingRight:node.paddingX})}if(_.has(node,"paddingY")){_.defaults(node,{paddingTop:node.paddingY,paddingBottom:node.paddingY})}if(_.has(node,"padding")){_.defaults(node,{paddingLeft:node.padding,paddingRight:node.padding,paddingTop:node.padding,paddingBottom:node.padding})}_.defaults(node,NODE_DEFAULT_ATTRS);_.each(["paddingLeft","paddingRight","paddingTop","paddingBottom"],function(k){node[k]=Number(node[k])});
|
||||
// Save dimensions for restore during post-processing
|
||||
if(_.has(node,"width")){node._prevWidth=node.width}if(_.has(node,"height")){node._prevHeight=node.height}});g.edges().forEach(function(e){var edge=g.edge(e);if(!_.has(edge,"label")){edge.label=""}_.defaults(edge,EDGE_DEFAULT_ATTRS)})}function postProcessGraph(g){_.each(g.nodes(),function(v){var node=g.node(v);
|
||||
// Restore original dimensions
|
||||
if(_.has(node,"_prevWidth")){node.width=node._prevWidth}else{delete node.width}if(_.has(node,"_prevHeight")){node.height=node._prevHeight}else{delete node.height}delete node._prevWidth;delete node._prevHeight})}function createOrSelectGroup(root,name){var selection=root.select("g."+name);if(selection.empty()){selection=root.append("g").attr("class",name)}return selection}},{"./arrows":2,"./create-clusters":3,"./create-edge-labels":4,"./create-edge-paths":5,"./create-nodes":6,"./d3":7,"./dagre":8,"./lodash":21,"./position-clusters":22,"./position-edge-labels":23,"./position-nodes":24,"./shapes":26}],26:[function(require,module,exports){"use strict";var intersectRect=require("./intersect/intersect-rect");var intersectEllipse=require("./intersect/intersect-ellipse");var intersectCircle=require("./intersect/intersect-circle");var intersectPolygon=require("./intersect/intersect-polygon");module.exports={rect:rect,ellipse:ellipse,circle:circle,diamond:diamond};function rect(parent,bbox,node){var shapeSvg=parent.insert("rect",":first-child").attr("rx",node.rx).attr("ry",node.ry).attr("x",-bbox.width/2).attr("y",-bbox.height/2).attr("width",bbox.width).attr("height",bbox.height);node.intersect=function(point){return intersectRect(node,point)};return shapeSvg}function ellipse(parent,bbox,node){var rx=bbox.width/2;var ry=bbox.height/2;var shapeSvg=parent.insert("ellipse",":first-child").attr("x",-bbox.width/2).attr("y",-bbox.height/2).attr("rx",rx).attr("ry",ry);node.intersect=function(point){return intersectEllipse(node,rx,ry,point)};return shapeSvg}function circle(parent,bbox,node){var r=Math.max(bbox.width,bbox.height)/2;var shapeSvg=parent.insert("circle",":first-child").attr("x",-bbox.width/2).attr("y",-bbox.height/2).attr("r",r);node.intersect=function(point){return intersectCircle(node,r,point)};return shapeSvg}
|
||||
// Circumscribe an ellipse for the bounding box with a diamond shape. I derived
|
||||
// the function to calculate the diamond shape from:
|
||||
// http://mathforum.org/kb/message.jspa?messageID=3750236
|
||||
function diamond(parent,bbox,node){var w=bbox.width*Math.SQRT2/2;var h=bbox.height*Math.SQRT2/2;var points=[{x:0,y:-h},{x:-w,y:0},{x:0,y:h},{x:w,y:0}];var shapeSvg=parent.insert("polygon",":first-child").attr("points",points.map(function(p){return p.x+","+p.y}).join(" "));node.intersect=function(p){return intersectPolygon(node,points,p)};return shapeSvg}},{"./intersect/intersect-circle":11,"./intersect/intersect-ellipse":12,"./intersect/intersect-polygon":15,"./intersect/intersect-rect":16}],27:[function(require,module,exports){var _=require("./lodash");
|
||||
// Public utility functions
|
||||
module.exports={isSubgraph:isSubgraph,edgeToId:edgeToId,applyStyle:applyStyle,applyClass:applyClass,applyTransition:applyTransition};
|
||||
/*
|
||||
* Returns true if the specified node in the graph is a subgraph node. A
|
||||
* subgraph node is one that contains other nodes.
|
||||
*/function isSubgraph(g,v){return!!g.children(v).length}function edgeToId(e){return escapeId(e.v)+":"+escapeId(e.w)+":"+escapeId(e.name)}var ID_DELIM=/:/g;function escapeId(str){return str?String(str).replace(ID_DELIM,"\\:"):""}function applyStyle(dom,styleFn){if(styleFn){dom.attr("style",styleFn)}}function applyClass(dom,classFn,otherClasses){if(classFn){dom.attr("class",classFn).attr("class",otherClasses+" "+dom.attr("class"))}}function applyTransition(selection,g){var graph=g.graph();if(_.isPlainObject(graph)){var transition=graph.transition;if(_.isFunction(transition)){return transition(selection)}}return selection}},{"./lodash":21}],28:[function(require,module,exports){module.exports="0.6.4"},{}]},{},[1])(1)});
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+31933
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+4816
File diff suppressed because one or more lines are too long
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
Generated
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: Arrows</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style id="css">
|
||||
body {
|
||||
font: 300 14px 'Helvetica Neue', Helvetica;
|
||||
}
|
||||
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
fill: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Dagre D3 Demo: Arrows</h1>
|
||||
|
||||
<svg width=960 height=600><g/></svg>
|
||||
|
||||
<section>
|
||||
<p>A sample that shows the different arrows available in dagre-d3.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create a new directed graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
["normal", "vee", "undirected"].forEach(function(arrowhead) {
|
||||
g.setNode(arrowhead + "1", { label: " " });
|
||||
g.setNode(arrowhead + "2", { label: " " });
|
||||
g.setEdge(arrowhead + "1", arrowhead + "2", {
|
||||
arrowhead: arrowhead,
|
||||
label: arrowhead
|
||||
});
|
||||
});
|
||||
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.select("g");
|
||||
|
||||
// Set up zoom support
|
||||
var zoom = d3.zoom().on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(inner, g);
|
||||
|
||||
// Center the graph
|
||||
var initialScale = 0.75;
|
||||
svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));
|
||||
|
||||
svg.attr('height', g.graph().height * initialScale + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+102
@@ -0,0 +1,102 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: Clusters</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<h1>Dagre D3 Demo: Clusters</h1>
|
||||
|
||||
<style id="css">
|
||||
.clusters rect {
|
||||
fill: #00ffd0;
|
||||
stroke: #999;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #999;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg id="svg-canvas" width=960 height=600></svg>
|
||||
|
||||
<section>
|
||||
<p>An example of visualizing clusters. This example shows
|
||||
how clusters can be applied to a rendered graph.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create the input graph
|
||||
var g = new dagreD3.graphlib.Graph({compound:true})
|
||||
.setGraph({})
|
||||
.setDefaultEdgeLabel(function() { return {}; });
|
||||
|
||||
// Here we're setting the nodes
|
||||
g.setNode('a', {label: 'A'});
|
||||
g.setNode('b', {label: 'B'});
|
||||
g.setNode('c', {label: 'C'});
|
||||
g.setNode('d', {label: 'D'});
|
||||
g.setNode('e', {label: 'E'});
|
||||
g.setNode('f', {label: 'F'});
|
||||
g.setNode('g', {label: 'G'});
|
||||
g.setNode('group', {label: 'Group', clusterLabelPos: 'top', style: 'fill: #d3d7e8'});
|
||||
g.setNode('top_group', {label: 'Top Group', clusterLabelPos: 'bottom', style: 'fill: #ffd47f'});
|
||||
g.setNode('bottom_group', {label: 'Bottom Group', style: 'fill: #5f9488'});
|
||||
|
||||
// Set the parents to define which nodes belong to which cluster
|
||||
g.setParent('top_group', 'group');
|
||||
g.setParent('bottom_group', 'group');
|
||||
g.setParent('b', 'top_group');
|
||||
g.setParent('c', 'bottom_group');
|
||||
g.setParent('d', 'bottom_group');
|
||||
g.setParent('e', 'bottom_group');
|
||||
g.setParent('f', 'bottom_group');
|
||||
|
||||
// Set up edges, no special attributes.
|
||||
g.setEdge('a', 'b');
|
||||
g.setEdge('b', 'c');
|
||||
g.setEdge('b', 'd');
|
||||
g.setEdge('b', 'e');
|
||||
g.setEdge('b', 'f');
|
||||
g.setEdge('b', 'g');
|
||||
|
||||
g.nodes().forEach(function(v) {
|
||||
var node = g.node(v);
|
||||
// Round the corners of the nodes
|
||||
node.rx = node.ry = 5;
|
||||
});
|
||||
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select("svg"),
|
||||
svgGroup = svg.append("g");
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(d3.select("svg g"), g);
|
||||
|
||||
// Center the graph
|
||||
var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
|
||||
svgGroup.attr("transform", "translate(" + xCenterOffset + ", 20)");
|
||||
svg.attr("height", g.graph().height + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
body {
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
color: #333;
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
||||
section p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
svg {
|
||||
border: 1px solid #ccc;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
pre {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
var bodyElem = d3.select('body'),
|
||||
jsElem = d3.select('#js'),
|
||||
jsPanel = bodyElem.append('div').attr('id', 'jsPanel');
|
||||
cssElem = d3.select('#css'),
|
||||
cssPanel = bodyElem.append('div').attr('id', 'cssPanel');
|
||||
|
||||
function setupPanel(panel, elem, title) {
|
||||
panel.append('h2').text(title);
|
||||
return panel.append('pre').append('code').text(elem.html().trim());
|
||||
}
|
||||
|
||||
var jsCode = setupPanel(jsPanel, jsElem, 'JavaScript');
|
||||
var cssCode = setupPanel(cssPanel, cssElem, 'CSS');
|
||||
|
||||
var hljsRoot = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.1';
|
||||
|
||||
bodyElem.append('link')
|
||||
.attr('rel', 'stylesheet')
|
||||
.attr('href', hljsRoot + '/styles/xcode.min.css');
|
||||
bodyElem.append('script')
|
||||
.attr('src', hljsRoot + '/highlight.min.js')
|
||||
.on('load', function() {
|
||||
hljs.highlightBlock(jsCode.node());
|
||||
hljs.highlightBlock(cssCode.node());
|
||||
});
|
||||
Generated
Vendored
+99
@@ -0,0 +1,99 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: DOM Example</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<h1>Dagre D3 Demo: DOM Example</h1>
|
||||
|
||||
<style id="css">
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
table td {
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
table td:first-child {
|
||||
background-color: #afa;
|
||||
border-top: 1px solid #333;
|
||||
border-left: 1px solid #333;
|
||||
border-bottom: 1px solid #333;
|
||||
border-radius: 5px 0 0 5px;
|
||||
}
|
||||
|
||||
table td:last-child {
|
||||
background-color: #faa;
|
||||
border-top: 1px solid #333;
|
||||
border-right: 1px solid #333;
|
||||
border-bottom: 1px solid #333;
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg width=960 height=600></svg>
|
||||
|
||||
<section>
|
||||
<p>A sample showing how to use DOM nodes in a graph. Note that IE does not
|
||||
support this technique.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create a new directed graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
g.setNode("root", {
|
||||
label: function() {
|
||||
var table = document.createElement("table"),
|
||||
tr = d3.select(table).append("tr");
|
||||
tr.append("td").text("A");
|
||||
tr.append("td").text("B");
|
||||
return table;
|
||||
},
|
||||
padding: 0,
|
||||
rx: 5,
|
||||
ry: 5
|
||||
});
|
||||
g.setNode("A", { label: "A", fill: "#afa" });
|
||||
g.setNode("B", { label: "B", fill: "#faa" });
|
||||
g.setEdge("root", "A", {});
|
||||
g.setEdge("root", "B", {});
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select('svg'),
|
||||
svgGroup = svg.append('g');
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(svgGroup, g);
|
||||
|
||||
// Center the graph
|
||||
var xCenterOffset = (svg.attr('width') - g.graph().width) / 2;
|
||||
svgGroup.attr('transform', 'translate(' + xCenterOffset + ', 20)');
|
||||
svg.attr('height', g.graph().height + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+286
@@ -0,0 +1,286 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Renderer Demo</title>
|
||||
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
|
||||
@-webkit-keyframes flash {
|
||||
0%, 50%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
25%, 75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flash {
|
||||
0%, 50%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
25%, 75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
.warn {
|
||||
-webkit-animation-duration: 5s;
|
||||
animation-duration: 5s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
animation-iteration-count: 1;
|
||||
}
|
||||
|
||||
.live.map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.live.map text {
|
||||
font-weight: 300;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.live.map .node rect {
|
||||
stroke-width: 1.5px;
|
||||
stroke: #bbb;
|
||||
fill: #666;
|
||||
}
|
||||
|
||||
.live.map .status {
|
||||
height: 100%;
|
||||
width: 15px;
|
||||
display: block;
|
||||
float: left;
|
||||
border-top-left-radius: 5px;
|
||||
border-bottom-left-radius: 5px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.live.map .running .status {
|
||||
background-color: #7f7;
|
||||
}
|
||||
|
||||
.live.map .running.warn .status {
|
||||
background-color: #ffed68;
|
||||
}
|
||||
|
||||
.live.map .stopped .status {
|
||||
background-color: #f77;
|
||||
}
|
||||
|
||||
.live.map .warn .queue {
|
||||
color: #f77;
|
||||
}
|
||||
|
||||
.warn {
|
||||
-webkit-animation-name: flash;
|
||||
animation-name: flash;
|
||||
}
|
||||
|
||||
.live.map .consumers {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.live.map .consumers,
|
||||
.live.map .name {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.live.map .consumers:after {
|
||||
content: "x";
|
||||
}
|
||||
|
||||
.live.map .queue {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 130px;
|
||||
height: 20px;
|
||||
font-size: 12px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.live.map .node g div {
|
||||
width: 200px;
|
||||
height: 40px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.live.map .node g div span.consumers {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.live.map .edgeLabel text {
|
||||
width: 50px;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.live.map .edgePath path {
|
||||
stroke: #999;
|
||||
stroke-width: 1.5px;
|
||||
fill: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="live map">
|
||||
<svg><g/></svg>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
var workers = {
|
||||
"identifier": {
|
||||
"consumers": 2,
|
||||
"count": 20
|
||||
},
|
||||
"lost-and-found": {
|
||||
"consumers": 1,
|
||||
"count": 1,
|
||||
"inputQueue": "identifier",
|
||||
"inputThroughput": 50
|
||||
},
|
||||
"monitor": {
|
||||
"consumers": 1,
|
||||
"count": 0,
|
||||
"inputQueue": "identifier",
|
||||
"inputThroughput": 50
|
||||
},
|
||||
"meta-enricher": {
|
||||
"consumers": 4,
|
||||
"count": 9900,
|
||||
"inputQueue": "identifier",
|
||||
"inputThroughput": 50
|
||||
},
|
||||
"geo-enricher": {
|
||||
"consumers": 2,
|
||||
"count": 1,
|
||||
"inputQueue": "meta-enricher",
|
||||
"inputThroughput": 50
|
||||
},
|
||||
"elasticsearch-writer": {
|
||||
"consumers": 0,
|
||||
"count": 9900,
|
||||
"inputQueue": "geo-enricher",
|
||||
"inputThroughput": 50
|
||||
}
|
||||
};
|
||||
|
||||
// Set up zoom support
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.select("g"),
|
||||
zoom = d3.zoom().on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Left-to-right layout
|
||||
var g = new dagreD3.graphlib.Graph();
|
||||
g.setGraph({
|
||||
nodesep: 70,
|
||||
ranksep: 50,
|
||||
rankdir: "LR",
|
||||
marginx: 20,
|
||||
marginy: 20
|
||||
});
|
||||
|
||||
function draw(isUpdate) {
|
||||
for (var id in workers) {
|
||||
var worker = workers[id];
|
||||
var className = worker.consumers ? "running" : "stopped";
|
||||
if (worker.count > 10000) {
|
||||
className += " warn";
|
||||
}
|
||||
var html = "<div>";
|
||||
html += "<span class=status></span>";
|
||||
html += "<span class=consumers>"+worker.consumers+"</span>";
|
||||
html += "<span class=name>"+id+"</span>";
|
||||
html += "<span class=queue><span class=counter>"+worker.count+"</span></span>";
|
||||
html += "</div>";
|
||||
g.setNode(id, {
|
||||
labelType: "html",
|
||||
label: html,
|
||||
rx: 5,
|
||||
ry: 5,
|
||||
padding: 0,
|
||||
class: className
|
||||
});
|
||||
|
||||
if (worker.inputQueue) {
|
||||
g.setEdge(worker.inputQueue, id, {
|
||||
label: worker.inputThroughput + "/s",
|
||||
width: 40
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
inner.call(render, g);
|
||||
|
||||
// Zoom and scale to fit
|
||||
var graphWidth = g.graph().width + 80;
|
||||
var graphHeight = g.graph().height + 40;
|
||||
var width = parseInt(svg.style("width").replace(/px/, ""));
|
||||
var height = parseInt(svg.style("height").replace(/px/, ""));
|
||||
var zoomScale = Math.min(width / graphWidth, height / graphHeight);
|
||||
var translateX = (width / 2) - ((graphWidth * zoomScale) / 2)
|
||||
var translateY = (height / 2) - ((graphHeight * zoomScale) / 2);
|
||||
var svgZoom = isUpdate ? svg.transition().duration(500) : svg;
|
||||
svgZoom.call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(zoomScale));
|
||||
}
|
||||
|
||||
// Do some mock queue status updates
|
||||
setInterval(function() {
|
||||
var stoppedWorker1Count = workers["elasticsearch-writer"].count;
|
||||
var stoppedWorker2Count = workers["meta-enricher"].count;
|
||||
for (var id in workers) {
|
||||
workers[id].count = Math.ceil(Math.random() * 3);
|
||||
if (workers[id].inputThroughput) workers[id].inputThroughput = Math.ceil(Math.random() * 250);
|
||||
}
|
||||
workers["elasticsearch-writer"].count = stoppedWorker1Count + Math.ceil(Math.random() * 100);
|
||||
workers["meta-enricher"].count = stoppedWorker2Count + Math.ceil(Math.random() * 100);
|
||||
draw(true);
|
||||
}, 1000);
|
||||
|
||||
// Do a mock change of worker configuration
|
||||
setInterval(function() {
|
||||
workers["elasticsearch-monitor"] = {
|
||||
"consumers": 0,
|
||||
"count": 0,
|
||||
"inputQueue": "elasticsearch-writer",
|
||||
"inputThroughput": 50
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
// Initial draw, once the DOM is ready
|
||||
document.addEventListener("DOMContentLoaded", draw);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
Vendored
+423
@@ -0,0 +1,423 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Graph Storyboard. Add and Prune Dependencies Algorithm</title>
|
||||
|
||||
<script src="https://d3js.org/d3.v4.js"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style id="css">
|
||||
h1 {
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 0.2em;
|
||||
}
|
||||
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.node polygon {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path.path {
|
||||
stroke: #333;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
div#top-frame {
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
div#WBS-frame {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
div#dependencies-frame {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
div#schedule-frame {
|
||||
float: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Polyfill for PhantomJS. This can be safely ignored if not using PhantomJS.
|
||||
// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
|
||||
if (!Function.prototype.bind) {
|
||||
Function.prototype.bind = function(oThis) {
|
||||
if (typeof this !== 'function') {
|
||||
// closest thing possible to the ECMAScript 5
|
||||
// internal IsCallable function
|
||||
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
|
||||
}
|
||||
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
fNOP = function() {},
|
||||
fBound = function() {
|
||||
return fToBind.apply(this instanceof fNOP && oThis
|
||||
? this
|
||||
: oThis,
|
||||
aArgs.concat(Array.prototype.slice.call(arguments)));
|
||||
};
|
||||
|
||||
fNOP.prototype = this.prototype;
|
||||
fBound.prototype = new fNOP();
|
||||
|
||||
return fBound;
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
var dagred3Story = function(svgelement, graphType, interframetime) {
|
||||
this.interframetime = interframetime;
|
||||
this.lastrenderTime = null;
|
||||
this.g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
//// Setup animation (if required)
|
||||
//this.g.graph().transition = function(selection) {
|
||||
// return selection.transition().duration(50);
|
||||
//}.bind(this);
|
||||
this.g.setDefaultEdgeLabel(function() { return {}; });
|
||||
this.g.graph().marginx = 10;
|
||||
this.g.graph().marginy = 10;
|
||||
switch(graphType) {
|
||||
case 'Work Breakdown Structure':
|
||||
this.WBS = true;
|
||||
this.Schedule = false;
|
||||
this.g.graph().ranksep = 30;
|
||||
this.g.graph().nodesep = 30;
|
||||
break;
|
||||
case 'Schedule Network':
|
||||
this.Schedule = true;
|
||||
this.WBS = false;
|
||||
this.g.graph().rankdir = "LR";
|
||||
this.g.graph().ranksep = 15;
|
||||
this.g.graph().nodesep = 15;
|
||||
break;
|
||||
default:
|
||||
console.log ("graphType of "+x+" is not implemented")
|
||||
}
|
||||
this.svg = d3.select(svgelement);
|
||||
this.inner = this.svg.append("g");
|
||||
this.svg.call(d3.zoom().on("zoom", (function() {
|
||||
this.inner.attr("transform", d3.event.transform)
|
||||
}).bind(this)));
|
||||
|
||||
this.t = 0;
|
||||
|
||||
this.dagreD3render = new dagreD3.render();
|
||||
};
|
||||
|
||||
dagred3Story.prototype.animateFrame = function(RenderAfter, Frame) {
|
||||
this.t += RenderAfter
|
||||
//var that = this;
|
||||
setTimeout(function() {
|
||||
Frame.forEach(function(x) {
|
||||
if (this.Schedule) {
|
||||
switch(x[0]) {
|
||||
case 'setActivity':
|
||||
this.g.setNode(x[1],{})
|
||||
break;
|
||||
case 'removeNode':
|
||||
this.g.removeNode(x[1])
|
||||
break;
|
||||
case 'setMilestone':
|
||||
this.g.setNode(x[1],{ shape: 'diamond', style: "fill: #fff; stroke: #000" })
|
||||
break;
|
||||
case 'AddCoherenceEdge':
|
||||
this.g.setEdge(x[1], x[2], {
|
||||
curve: d3.curveBasis
|
||||
});
|
||||
break;
|
||||
case 'AddDependencyEdge':
|
||||
this.g.setEdge(x[1], x[2], {
|
||||
curve: d3.curveBasis
|
||||
,label: 'added'
|
||||
,labeloffset: 5
|
||||
,labelpos: 'l'
|
||||
});
|
||||
break;
|
||||
case 'MakeRedundantEdge':
|
||||
this.g.setEdge(x[1], x[2], {
|
||||
style: "stroke: #aaa; stroke-dasharray: 5, 10;"
|
||||
,curve: d3.curveBasis
|
||||
,arrowheadStyle: "fill: #aaa"
|
||||
,labelpos: 'c'
|
||||
,label: 'pruned'
|
||||
,labelStyle: 'stroke: #aaa'
|
||||
});
|
||||
break;
|
||||
case 'RemoveEdge':
|
||||
this.g.removeEdge(x[1], x[2]);
|
||||
break;
|
||||
default:
|
||||
console.log ("Schedule Network element "+x+" is not implemented")
|
||||
}
|
||||
} else if (this.WBS ) {
|
||||
switch(x[0]) {
|
||||
case 'setComponent':
|
||||
this.g.setNode(x[1],{})
|
||||
break;
|
||||
case 'AddWBSEdge':
|
||||
this.g.setEdge(x[1], x[2], {
|
||||
arrowhead: 'undirected'
|
||||
});
|
||||
break;
|
||||
default:
|
||||
console.log ("WBS element "+x+" is not implemented")
|
||||
}
|
||||
}
|
||||
}.bind(this))
|
||||
|
||||
if (this.g) {
|
||||
// Render
|
||||
this.dagreD3render(this.inner,this.g);
|
||||
}
|
||||
}.bind(this), this.t)
|
||||
};
|
||||
|
||||
dagred3Story.prototype.animateStory = function(RenderAfter, Story) {
|
||||
this.t += RenderAfter
|
||||
setTimeout(function() {
|
||||
Story.forEach(function(Frame) {
|
||||
this.animateFrame(this.interframetime, Frame);
|
||||
}.bind(this))
|
||||
}.bind(this), this.t)
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<div id="top-frame">
|
||||
<div id="WBS-frame">
|
||||
<h1>WBS</h1>
|
||||
<svg id="WBS" width=250 height=250></svg>
|
||||
</div>
|
||||
|
||||
<div id="dependencies-frame">
|
||||
<h1>Sequencing</h1>
|
||||
<svg id="dependencies" width=300 height=250></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="schedule-frame">
|
||||
<h1>Coherent Schedule Network</h1>
|
||||
<svg id="schedule" width=1150 height=500></svg>
|
||||
</div>
|
||||
|
||||
<script id="js">
|
||||
var framedelay = 2000;
|
||||
var dependenciesstory = new dagred3Story("#dependencies", "Schedule Network", framedelay);
|
||||
dependenciesstory.animateStory(0,
|
||||
[
|
||||
[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
]
|
||||
,[
|
||||
["setActivity", "A.1"]
|
||||
,
|
||||
["setMilestone", "A.2 Start"]
|
||||
,
|
||||
["AddDependencyEdge", "A.1", "A.2 Start"]
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
["setActivity", "A.2.2"]
|
||||
,
|
||||
["setActivity", "A.2.3"]
|
||||
,
|
||||
["AddDependencyEdge", "A.2.2", "A.2.3"]
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
],[
|
||||
["setActivity", "A.2.1"]
|
||||
,
|
||||
["setActivity", "B"]
|
||||
,
|
||||
["AddDependencyEdge", "A.2.1", "B"]
|
||||
],[
|
||||
|
||||
],[
|
||||
|
||||
]
|
||||
]);
|
||||
|
||||
var WBSstory = new dagred3Story("#WBS", "Work Breakdown Structure", framedelay);
|
||||
|
||||
WBSstory.animateStory(0,
|
||||
[
|
||||
[
|
||||
["setComponent", "Project"]
|
||||
],[
|
||||
["setComponent", "A"]
|
||||
,
|
||||
["AddWBSEdge", "Project", "A"]
|
||||
,
|
||||
["setComponent", "B"]
|
||||
,
|
||||
["AddWBSEdge", "Project", "B"]
|
||||
],[
|
||||
["setComponent", "A.1"]
|
||||
,
|
||||
["AddWBSEdge", "A", "A.1"]
|
||||
,
|
||||
["setComponent", "A.2"]
|
||||
,
|
||||
["AddWBSEdge", "A", "A.2"]
|
||||
],[
|
||||
["setComponent", "A.2.1"]
|
||||
,
|
||||
["AddWBSEdge", "A.2", "A.2.1"]
|
||||
,
|
||||
["setComponent", "A.2.2"]
|
||||
,
|
||||
["AddWBSEdge", "A.2", "A.2.2"]
|
||||
,
|
||||
["setComponent", "A.2.3"]
|
||||
,
|
||||
["AddWBSEdge", "A.2", "A.2.3"]
|
||||
]
|
||||
]);
|
||||
|
||||
var schedulestory = new dagred3Story("#schedule", "Schedule Network",framedelay);
|
||||
|
||||
// Create the input graph
|
||||
|
||||
schedulestory.animateStory(0,
|
||||
[
|
||||
[
|
||||
["setActivity", "Project"]
|
||||
],[
|
||||
["removeNode", "Project"]
|
||||
,
|
||||
["setMilestone", "Project Finish"]
|
||||
,
|
||||
["setMilestone", "Project Start"]
|
||||
,
|
||||
["setActivity", "A"]
|
||||
,
|
||||
["setActivity", "B"]
|
||||
,
|
||||
["AddCoherenceEdge", "Project Start", "A"]
|
||||
,
|
||||
["AddCoherenceEdge", "Project Start", "B"]
|
||||
,
|
||||
["AddCoherenceEdge", "A", "Project Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "B", "Project Finish"]
|
||||
],[
|
||||
["removeNode", "A"]
|
||||
,
|
||||
["setMilestone", "A Start"]
|
||||
,
|
||||
["setActivity", "A.1"]
|
||||
,
|
||||
["setActivity", "A.2"]
|
||||
,
|
||||
["setMilestone", "A Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "A Start", "A.1"]
|
||||
,
|
||||
["AddCoherenceEdge", "A Start", "A.2"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.1", "A Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2", "A Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "Project Start", "A Start"]
|
||||
,
|
||||
["AddCoherenceEdge", "A Finish", "Project Finish"]
|
||||
],[
|
||||
["removeNode", "A.2"]
|
||||
,
|
||||
["setMilestone", "A.2 Start"]
|
||||
,
|
||||
["setActivity", "A.2.1"]
|
||||
,
|
||||
["setActivity", "A.2.2"]
|
||||
,
|
||||
["setActivity", "A.2.3"]
|
||||
,
|
||||
["setMilestone", "A.2 Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2 Start", "A.2.1"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2 Start", "A.2.2"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2 Start", "A.2.3"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2.1", "A.2 Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2.2", "A.2 Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2.3", "A.2 Finish"]
|
||||
,
|
||||
["AddCoherenceEdge", "A Start", "A.2 Start"]
|
||||
,
|
||||
["AddCoherenceEdge", "A.2 Finish", "A Finish"]
|
||||
]
|
||||
,[
|
||||
["AddDependencyEdge", "A.1", "A.2 Start"]
|
||||
],[
|
||||
["MakeRedundantEdge", "A Start", "A.2 Start"]
|
||||
],[
|
||||
["MakeRedundantEdge", "A.1", "A Finish"]
|
||||
],[
|
||||
["RemoveEdge", "A Start", "A.2 Start"]
|
||||
],[
|
||||
["RemoveEdge", "A.1", "A Finish"]
|
||||
],[
|
||||
["AddDependencyEdge", "A.2.2", "A.2.3"]
|
||||
],[
|
||||
["MakeRedundantEdge", "A.2 Start", "A.2.3"]
|
||||
],[
|
||||
["MakeRedundantEdge", "A.2.2", "A.2 Finish"]
|
||||
],[
|
||||
["RemoveEdge", "A.2 Start", "A.2.3"]
|
||||
],[
|
||||
["RemoveEdge", "A.2.2", "A.2 Finish"]
|
||||
],[
|
||||
["AddDependencyEdge", "A.2.1", "B"]
|
||||
],[
|
||||
["MakeRedundantEdge", "Project Start", "B"]
|
||||
],[
|
||||
["RemoveEdge", "Project Start", "B"]
|
||||
]
|
||||
]);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
Vendored
+195
@@ -0,0 +1,195 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: Tooltip on Hover</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<!-- Pull in JQuery dependencies -->
|
||||
<link rel="stylesheet" href="tipsy.css">
|
||||
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||
<script src="tipsy.js"></script>
|
||||
|
||||
<h1>Dagre D3 Demo: Tooltip on Hover</h1>
|
||||
|
||||
<style id="css">
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
fill: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.node text {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* This styles the title of the tooltip */
|
||||
.tipsy .name {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
color: #60b1fc;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* This styles the body of the tooltip */
|
||||
.tipsy .description {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg width=960 height=600></svg>
|
||||
|
||||
<section>
|
||||
<p>The TCP state diagram
|
||||
(<a href="http://www.rfc-editor.org/rfc/rfc793.txt">source: RFC 793</a>) with
|
||||
hover support. Uses <a href="http://bl.ocks.org/ilyabo/1373263">tipsy JS and CSS</a>
|
||||
for the tooltip.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create a new directed graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
// States and transitions from RFC 793
|
||||
var states = {
|
||||
CLOSED: {
|
||||
description: "represents no connection state at all.",
|
||||
style: "fill: #f77"
|
||||
},
|
||||
|
||||
LISTEN: {
|
||||
description: "represents waiting for a connection request from any " +
|
||||
"remote TCP and port."
|
||||
},
|
||||
|
||||
"SYN SENT": {
|
||||
description: "represents waiting for a matching connection " +
|
||||
"request after having sent a connection request."
|
||||
},
|
||||
|
||||
"SYN RCVD": {
|
||||
description: "represents waiting for a confirming connection " +
|
||||
"request acknowledgment after having both received and sent a " +
|
||||
"connection request."
|
||||
},
|
||||
|
||||
|
||||
ESTAB: {
|
||||
description: "represents an open connection, data received " +
|
||||
"can be delivered to the user. The normal state for the data " +
|
||||
"transfer phase of the connection.",
|
||||
style: "fill: #7f7"
|
||||
},
|
||||
|
||||
"FINWAIT-1": {
|
||||
description: "represents waiting for a connection termination " +
|
||||
"request from the remote TCP, or an acknowledgment of the " +
|
||||
"connection termination request previously sent."
|
||||
|
||||
},
|
||||
|
||||
"FINWAIT-2": {
|
||||
description: "represents waiting for a connection termination " +
|
||||
"request from the remote TCP."
|
||||
},
|
||||
|
||||
|
||||
"CLOSE WAIT": {
|
||||
description: "represents waiting for a connection termination " +
|
||||
"request from the local user."
|
||||
},
|
||||
|
||||
CLOSING: {
|
||||
description: "represents waiting for a connection termination " +
|
||||
"request acknowledgment from the remote TCP."
|
||||
},
|
||||
|
||||
"LAST-ACK": {
|
||||
description: "represents waiting for an acknowledgment of the " +
|
||||
"connection termination request previously sent to the remote " +
|
||||
"TCP (which includes an acknowledgment of its connection " +
|
||||
"termination request)."
|
||||
},
|
||||
|
||||
"TIME WAIT": {
|
||||
description: "represents waiting for enough time to pass to be " +
|
||||
"sure the remote TCP received the acknowledgment of its " +
|
||||
"connection termination request."
|
||||
}
|
||||
};
|
||||
|
||||
// Add states to the graph, set labels, and style
|
||||
Object.keys(states).forEach(function(state) {
|
||||
var value = states[state];
|
||||
value.label = state;
|
||||
value.rx = value.ry = 5;
|
||||
g.setNode(state, value);
|
||||
});
|
||||
|
||||
// Set up the edges
|
||||
g.setEdge("CLOSED", "LISTEN", { label: "open" });
|
||||
g.setEdge("LISTEN", "SYN RCVD", { label: "rcv SYN" });
|
||||
g.setEdge("LISTEN", "SYN SENT", { label: "send" });
|
||||
g.setEdge("LISTEN", "CLOSED", { label: "close" });
|
||||
g.setEdge("SYN RCVD", "FINWAIT-1", { label: "close" });
|
||||
g.setEdge("SYN RCVD", "ESTAB", { label: "rcv ACK of SYN" });
|
||||
g.setEdge("SYN SENT", "SYN RCVD", { label: "rcv SYN" });
|
||||
g.setEdge("SYN SENT", "ESTAB", { label: "rcv SYN, ACK" });
|
||||
g.setEdge("SYN SENT", "CLOSED", { label: "close" });
|
||||
g.setEdge("ESTAB", "FINWAIT-1", { label: "close" });
|
||||
g.setEdge("ESTAB", "CLOSE WAIT", { label: "rcv FIN" });
|
||||
g.setEdge("FINWAIT-1", "FINWAIT-2", { label: "rcv ACK of FIN" });
|
||||
g.setEdge("FINWAIT-1", "CLOSING", { label: "rcv FIN" });
|
||||
g.setEdge("CLOSE WAIT", "LAST-ACK", { label: "close" });
|
||||
g.setEdge("FINWAIT-2", "TIME WAIT", { label: "rcv FIN" });
|
||||
g.setEdge("CLOSING", "TIME WAIT", { label: "rcv ACK of FIN" });
|
||||
g.setEdge("LAST-ACK", "CLOSED", { label: "rcv ACK of FIN" });
|
||||
g.setEdge("TIME WAIT", "CLOSED", { label: "timeout=2MSL" });
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.append("g");
|
||||
|
||||
// Set up zoom support
|
||||
var zoom = d3.zoom()
|
||||
.on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
// Simple function to style the tooltip for the given node.
|
||||
var styleTooltip = function(name, description) {
|
||||
return "<p class='name'>" + name + "</p><p class='description'>" + description + "</p>";
|
||||
};
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(inner, g);
|
||||
|
||||
inner.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 }); });
|
||||
|
||||
// Center the graph
|
||||
var initialScale = 0.75;
|
||||
svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));
|
||||
|
||||
svg.attr('height', g.graph().height * initialScale + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre Interactive Demo</title>
|
||||
|
||||
<script src="https://d3js.org/d3.v4.js"></script>
|
||||
<script src="https://dagrejs.github.io/project/graphlib-dot/v0.6.3/graphlib-dot.js"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style>
|
||||
svg {
|
||||
border: 1px solid #999;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.node {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.cluster rect {
|
||||
stroke: #333;
|
||||
fill: #000;
|
||||
fill-opacity: 0.1;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path.path {
|
||||
stroke: #333;
|
||||
stroke-width: 1.5px;
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
h1, h2 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-top: 1em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body onLoad="tryDraw();">
|
||||
|
||||
<h1>Dagre Interactive Demo</h1>
|
||||
|
||||
<h2>Input</h2>
|
||||
|
||||
<form>
|
||||
<label for="inputGraph">Graphviz Definition</label>
|
||||
<textarea id="inputGraph" rows="5" style="display: block" onKeyUp="tryDraw();">
|
||||
/* Example */
|
||||
digraph {
|
||||
/* Note: HTML labels do not work in IE, which lacks support for <foreignObject> tags. */
|
||||
node [rx=5 ry=5 labelStyle="font: 300 14px 'Helvetica Neue', Helvetica"]
|
||||
edge [labelStyle="font: 300 14px 'Helvetica Neue', Helvetica"]
|
||||
A [labelType="html"
|
||||
label="A <span style='font-size:32px'>Big</span> <span style='color:red;'>HTML</span> Source!"];
|
||||
C;
|
||||
E [label="Bold Red Sink" style="fill: #f77; font-weight: bold"];
|
||||
A -> B -> C;
|
||||
B -> D [label="A blue label" labelStyle="fill: #55f; font-weight: bold;"];
|
||||
D -> E [label="A thick red edge" style="stroke: #f77; stroke-width: 2px;" arrowheadStyle="fill: #f77"];
|
||||
C -> E;
|
||||
A -> D [labelType="html" label="A multi-rank <span style='color:blue;'>HTML</span> edge!"];
|
||||
}
|
||||
</textarea>
|
||||
|
||||
<a id="graphLink">Link for this graph</a>
|
||||
</form>
|
||||
|
||||
<h2>Graph Visualization</h2>
|
||||
|
||||
<svg width=800 height=600>
|
||||
<g/>
|
||||
</svg>
|
||||
|
||||
<script>
|
||||
// Input related code goes here
|
||||
|
||||
function graphToURL() {
|
||||
var elems = [window.location.protocol, '//',
|
||||
window.location.host,
|
||||
window.location.pathname,
|
||||
'?'];
|
||||
|
||||
var queryParams = [];
|
||||
if (debugAlignment) {
|
||||
queryParams.push('alignment=' + debugAlignment);
|
||||
}
|
||||
queryParams.push('graph=' + encodeURIComponent(inputGraph.value));
|
||||
elems.push(queryParams.join('&'));
|
||||
|
||||
return elems.join('');
|
||||
}
|
||||
|
||||
var inputGraph = document.querySelector("#inputGraph");
|
||||
|
||||
var graphLink = d3.select("#graphLink");
|
||||
|
||||
var oldInputGraphValue;
|
||||
|
||||
var graphRE = /[?&]graph=([^&]+)/;
|
||||
var graphMatch = window.location.search.match(graphRE);
|
||||
if (graphMatch) {
|
||||
inputGraph.value = decodeURIComponent(graphMatch[1]);
|
||||
}
|
||||
var debugAlignmentRE = /[?&]alignment=([^&]+)/;
|
||||
var debugAlignmentMatch = window.location.search.match(debugAlignmentRE);
|
||||
var debugAlignment;
|
||||
if (debugAlignmentMatch) debugAlignment = debugAlignmentMatch[1];
|
||||
|
||||
// Set up zoom support
|
||||
var svg = d3.select("svg"),
|
||||
inner = d3.select("svg g"),
|
||||
zoom = d3.zoom().on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
// Create and configure the renderer
|
||||
var render = dagreD3.render();
|
||||
|
||||
var g;
|
||||
function tryDraw() {
|
||||
if (oldInputGraphValue !== inputGraph.value) {
|
||||
inputGraph.setAttribute("class", "");
|
||||
oldInputGraphValue = inputGraph.value;
|
||||
try {
|
||||
g = graphlibDot.read(inputGraph.value);
|
||||
} catch (e) {
|
||||
inputGraph.setAttribute("class", "error");
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Save link to new graph
|
||||
graphLink.attr("href", graphToURL());
|
||||
|
||||
// Set margins, if not present
|
||||
if (!g.graph().hasOwnProperty("marginx") &&
|
||||
!g.graph().hasOwnProperty("marginy")) {
|
||||
g.graph().marginx = 20;
|
||||
g.graph().marginy = 20;
|
||||
}
|
||||
|
||||
g.graph().transition = function(selection) {
|
||||
return selection.transition().duration(500);
|
||||
};
|
||||
|
||||
// Render the graph into svg g
|
||||
d3.select("svg g").call(render, g);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Generated
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: Sentence Tokenization</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<h1>Dagre D3 Demo: Sentence Tokenization</h1>
|
||||
|
||||
<style id="css">
|
||||
/* This sets the color for "TK" nodes to a light blue green. */
|
||||
g.type-TK > rect {
|
||||
fill: #00ffd0;
|
||||
}
|
||||
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #999;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg id="svg-canvas" width=960 height=600></svg>
|
||||
|
||||
<section>
|
||||
<p>An example of visualizing the tokenization of a sentence. This example shows
|
||||
how CSS classes can be applied to a rendered graph.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create the input graph
|
||||
var g = new dagreD3.graphlib.Graph()
|
||||
.setGraph({})
|
||||
.setDefaultEdgeLabel(function() { return {}; });
|
||||
|
||||
// Here we're setting nodeclass, which is used by our custom drawNodes function
|
||||
// below.
|
||||
g.setNode(0, { label: "TOP", class: "type-TOP" });
|
||||
g.setNode(1, { label: "S", class: "type-S" });
|
||||
g.setNode(2, { label: "NP", class: "type-NP" });
|
||||
g.setNode(3, { label: "DT", class: "type-DT" });
|
||||
g.setNode(4, { label: "This", class: "type-TK" });
|
||||
g.setNode(5, { label: "VP", class: "type-VP" });
|
||||
g.setNode(6, { label: "VBZ", class: "type-VBZ" });
|
||||
g.setNode(7, { label: "is", class: "type-TK" });
|
||||
g.setNode(8, { label: "NP", class: "type-NP" });
|
||||
g.setNode(9, { label: "DT", class: "type-DT" });
|
||||
g.setNode(10, { label: "an", class: "type-TK" });
|
||||
g.setNode(11, { label: "NN", class: "type-NN" });
|
||||
g.setNode(12, { label: "example", class: "type-TK" });
|
||||
g.setNode(13, { label: ".", class: "type-." });
|
||||
g.setNode(14, { label: "sentence", class: "type-TK" });
|
||||
|
||||
g.nodes().forEach(function(v) {
|
||||
var node = g.node(v);
|
||||
// Round the corners of the nodes
|
||||
node.rx = node.ry = 5;
|
||||
});
|
||||
|
||||
// Set up edges, no special attributes.
|
||||
g.setEdge(3, 4);
|
||||
g.setEdge(2, 3);
|
||||
g.setEdge(1, 2);
|
||||
g.setEdge(6, 7);
|
||||
g.setEdge(5, 6);
|
||||
g.setEdge(9, 10);
|
||||
g.setEdge(8, 9);
|
||||
g.setEdge(11,12);
|
||||
g.setEdge(8, 11);
|
||||
g.setEdge(5, 8);
|
||||
g.setEdge(1, 5);
|
||||
g.setEdge(13,14);
|
||||
g.setEdge(1, 13);
|
||||
g.setEdge(0, 1)
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select("svg"),
|
||||
svgGroup = svg.append("g");
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(d3.select("svg g"), g);
|
||||
|
||||
// Center the graph
|
||||
var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
|
||||
svgGroup.attr("transform", "translate(" + xCenterOffset + ", 20)");
|
||||
svg.attr("height", g.graph().height + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+70
@@ -0,0 +1,70 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: Shapes</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style id="css">
|
||||
body {
|
||||
font: 300 14px 'Helvetica Neue', Helvetica;
|
||||
}
|
||||
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse,
|
||||
.node polygon {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
fill: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Dagre D3 Demo: Shapes</h1>
|
||||
|
||||
<svg width=960 height=600><g/></svg>
|
||||
|
||||
<section>
|
||||
<p>A sample that shows the different node shapes available in dagre-d3.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create a new directed graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
g.setNode("rect", { shape: "rect" });
|
||||
g.setNode("circle", { shape: "circle" });
|
||||
g.setNode("ellipse", { shape: "ellipse" });
|
||||
g.setNode("diamond", { shape: "diamond" });
|
||||
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.select("g");
|
||||
|
||||
// Set up zoom support
|
||||
var zoom = d3.zoom().on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(inner, g);
|
||||
|
||||
// Center the graph
|
||||
var initialScale = 0.75;
|
||||
svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));
|
||||
|
||||
svg.attr('height', g.graph().height * initialScale + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+106
@@ -0,0 +1,106 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: Style Attributes</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<h1>Dagre D3 Demo: Style Attributes</h1>
|
||||
|
||||
<style id="css">
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path.path {
|
||||
stroke: #333;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.arrowhead {
|
||||
stroke: blue;
|
||||
fill: blue;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<svg id="svg" width=960 height=600></svg>
|
||||
|
||||
<section>
|
||||
<p>An example showing how styles that are set in the input graph can be applied
|
||||
to nodes, node labels, edges, and edge labels in the rendered graph.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create the input graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
// Fill node "A" with the color green
|
||||
g.setNode("A", { style: "fill: #afa" });
|
||||
|
||||
// Make the label for node "B" bold
|
||||
g.setNode("B", { labelStyle: "font-weight: bold" });
|
||||
|
||||
// Double the size of the font for node "C"
|
||||
g.setNode("C", { labelStyle: "font-size: 2em" });
|
||||
|
||||
g.setNode("D", {});
|
||||
|
||||
g.setNode("E", {});
|
||||
|
||||
// Make the edge from "A" to "B" red, thick, and dashed
|
||||
g.setEdge("A", "B", {
|
||||
style: "stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;",
|
||||
arrowheadStyle: "fill: #f66"
|
||||
});
|
||||
|
||||
// Make the label for the edge from "C" to "B" italic and underlined
|
||||
g.setEdge("C", "B", {
|
||||
label: "A to C",
|
||||
labelStyle: "font-style: italic; text-decoration: underline;"
|
||||
});
|
||||
|
||||
// Make the edge between A and D smoother.
|
||||
// see available options for lineInterpolate here: https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate
|
||||
g.setEdge("A", "D", {
|
||||
label: "line interpolation different",
|
||||
curve: d3.curveBasis
|
||||
});
|
||||
|
||||
g.setEdge("E", "D", {});
|
||||
|
||||
// Make the arrowhead blue
|
||||
g.setEdge("A", "E", {
|
||||
label: "Arrowhead class",
|
||||
arrowheadClass: 'arrowhead'
|
||||
});
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.append("g");
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(inner, g);
|
||||
|
||||
// Center the graph
|
||||
var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
|
||||
inner.attr("transform", "translate(" + xCenterOffset + ", 20)");
|
||||
svg.attr("height", g.graph().height + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+103
@@ -0,0 +1,103 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: SVG Labels</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<h1>Dagre D3 Demo: SVG Labels</h1>
|
||||
|
||||
<style id="css">
|
||||
text {
|
||||
font-weight: 300;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serf;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #999;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<svg id="svg-canvas" width=960 height=600></svg>
|
||||
|
||||
<section>
|
||||
<p>An example of adding SVG labels. This allows the user to add any svg
|
||||
elements to the label. This allows for links to works in IE.</p>
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create the input graph
|
||||
var g = new dagreD3.graphlib.Graph()
|
||||
.setGraph({})
|
||||
.setDefaultEdgeLabel(function() { return {}; });
|
||||
|
||||
// Create the SVG label to pass in
|
||||
// Must create in SVG namespace
|
||||
// http://stackoverflow.com/questions/7547117/add-a-new-line-in-svg-bug-cannot-see-the-line
|
||||
// This mimics the same way string labels get added in Dagre-D3
|
||||
svg_label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
tspan = document.createElementNS('http://www.w3.org/2000/svg','tspan');
|
||||
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||
tspan.setAttribute('dy', '1em');
|
||||
tspan.setAttribute('x', '1');
|
||||
link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
link.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://google.com/');
|
||||
link.setAttribute('target', '_blank');
|
||||
link.textContent = 'IE Capable link';
|
||||
tspan.appendChild(link);
|
||||
svg_label.appendChild(tspan);
|
||||
|
||||
g.setNode(0, { label: svg_label, labelType: 'svg' });
|
||||
g.setNode(1, { label: "A" });
|
||||
g.setNode(2, { label: "B" });
|
||||
|
||||
g.nodes().forEach(function(v) {
|
||||
var node = g.node(v);
|
||||
// Round the corners of the nodes
|
||||
node.rx = node.ry = 5;
|
||||
});
|
||||
|
||||
svg_edge_label = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
edge_tspan = document.createElementNS('http://www.w3.org/2000/svg','tspan');
|
||||
edge_tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
|
||||
edge_tspan.setAttribute('dy', '1em');
|
||||
edge_tspan.setAttribute('x', '1');
|
||||
edge_link = document.createElementNS('http://www.w3.org/2000/svg', 'a');
|
||||
edge_link.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', 'http://google.com/');
|
||||
edge_link.setAttribute('target', '_blank');
|
||||
edge_link.textContent = 'IE Capable Edge link';
|
||||
edge_tspan.appendChild(edge_link);
|
||||
svg_edge_label.appendChild(edge_tspan);
|
||||
|
||||
// Set up edges, no special attributes.
|
||||
g.setEdge(0, 1, { labelType: "svg", label: svg_edge_label });
|
||||
g.setEdge(0, 2);
|
||||
g.setEdge(1, 2);
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Set up an SVG group so that we can translate the final graph.
|
||||
var svg = d3.select("svg"),
|
||||
svgGroup = svg.append("g");
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(d3.select("svg g"), g);
|
||||
|
||||
// Center the graph
|
||||
var xCenterOffset = (svg.attr("width") - g.graph().width) / 2;
|
||||
svgGroup.attr("transform", "translate(" + xCenterOffset + ", 20)");
|
||||
svg.attr("height", g.graph().height + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+102
@@ -0,0 +1,102 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: TCP State Diagram</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style id="css">
|
||||
body {
|
||||
font: 300 14px 'Helvetica Neue', Helvetica;
|
||||
}
|
||||
|
||||
.node rect {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.edgePath path {
|
||||
stroke: #333;
|
||||
fill: #333;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Dagre D3 Demo: TCP State Diagram</h1>
|
||||
|
||||
<svg width=960 height=600><g/></svg>
|
||||
|
||||
<section>
|
||||
<p>A sample rendering of a TCP state diagram
|
||||
(<a href="http://www.rfc-editor.org/rfc/rfc793.txt">RFC 793</a>). This example
|
||||
shows how to set custom styles in the input graph and how to set a custom
|
||||
initial zoom.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create a new directed graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
// States and transitions from RFC 793
|
||||
var states = [ "CLOSED", "LISTEN", "SYN RCVD", "SYN SENT",
|
||||
"ESTAB", "FINWAIT-1", "CLOSE WAIT", "FINWAIT-2",
|
||||
"CLOSING", "LAST-ACK", "TIME WAIT" ];
|
||||
|
||||
// Automatically label each of the nodes
|
||||
states.forEach(function(state) { g.setNode(state, { label: state }); });
|
||||
|
||||
// Set up the edges
|
||||
g.setEdge("CLOSED", "LISTEN", { label: "open" });
|
||||
g.setEdge("LISTEN", "SYN RCVD", { label: "rcv SYN" });
|
||||
g.setEdge("LISTEN", "SYN SENT", { label: "send" });
|
||||
g.setEdge("LISTEN", "CLOSED", { label: "close" });
|
||||
g.setEdge("SYN RCVD", "FINWAIT-1", { label: "close" });
|
||||
g.setEdge("SYN RCVD", "ESTAB", { label: "rcv ACK of SYN" });
|
||||
g.setEdge("SYN SENT", "SYN RCVD", { label: "rcv SYN" });
|
||||
g.setEdge("SYN SENT", "ESTAB", { label: "rcv SYN, ACK" });
|
||||
g.setEdge("SYN SENT", "CLOSED", { label: "close" });
|
||||
g.setEdge("ESTAB", "FINWAIT-1", { label: "close" });
|
||||
g.setEdge("ESTAB", "CLOSE WAIT", { label: "rcv FIN" });
|
||||
g.setEdge("FINWAIT-1", "FINWAIT-2", { label: "rcv ACK of FIN" });
|
||||
g.setEdge("FINWAIT-1", "CLOSING", { label: "rcv FIN" });
|
||||
g.setEdge("CLOSE WAIT", "LAST-ACK", { label: "close" });
|
||||
g.setEdge("FINWAIT-2", "TIME WAIT", { label: "rcv FIN" });
|
||||
g.setEdge("CLOSING", "TIME WAIT", { label: "rcv ACK of FIN" });
|
||||
g.setEdge("LAST-ACK", "CLOSED", { label: "rcv ACK of FIN" });
|
||||
g.setEdge("TIME WAIT", "CLOSED", { label: "timeout=2MSL" });
|
||||
|
||||
// Set some general styles
|
||||
g.nodes().forEach(function(v) {
|
||||
var node = g.node(v);
|
||||
node.rx = node.ry = 5;
|
||||
});
|
||||
|
||||
// Add some custom colors based on state
|
||||
g.node('CLOSED').style = "fill: #f77";
|
||||
g.node('ESTAB').style = "fill: #7f7";
|
||||
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.select("g");
|
||||
|
||||
// Set up zoom support
|
||||
var zoom = d3.zoom().on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(inner, g);
|
||||
|
||||
// Center the graph
|
||||
var initialScale = 0.75;
|
||||
svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));
|
||||
|
||||
svg.attr('height', g.graph().height * initialScale + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
.tipsy { font-size: 10px; position: absolute; padding: 5px; z-index: 100000; }
|
||||
.tipsy-inner { background-color: #000; color: #FFF; max-width: 200px; padding: 5px 8px 4px 8px; text-align: center; }
|
||||
|
||||
/* Rounded corners */
|
||||
.tipsy-inner { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; }
|
||||
|
||||
/* Uncomment for shadow */
|
||||
.tipsy-inner { box-shadow: 0 0 5px #000000; -webkit-box-shadow: 0 0 5px #000000; -moz-box-shadow: 0 0 5px #000000; }
|
||||
|
||||
.tipsy-arrow { position: absolute; width: 0; height: 0; line-height: 0; border: 5px dashed #000; }
|
||||
|
||||
/* Rules to colour arrows */
|
||||
.tipsy-arrow-n { border-bottom-color: #000; }
|
||||
.tipsy-arrow-s { border-top-color: #000; }
|
||||
.tipsy-arrow-e { border-left-color: #000; }
|
||||
.tipsy-arrow-w { border-right-color: #000; }
|
||||
|
||||
.tipsy-n .tipsy-arrow { top: 0px; left: 50%; margin-left: -5px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-nw .tipsy-arrow { top: 0; left: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
||||
.tipsy-ne .tipsy-arrow { top: 0; right: 10px; border-bottom-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent;}
|
||||
.tipsy-s .tipsy-arrow { bottom: 0; left: 50%; margin-left: -5px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-sw .tipsy-arrow { bottom: 0; left: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-se .tipsy-arrow { bottom: 0; right: 10px; border-top-style: solid; border-bottom: none; border-left-color: transparent; border-right-color: transparent; }
|
||||
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
|
||||
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
|
||||
Generated
Vendored
+288
@@ -0,0 +1,288 @@
|
||||
// tipsy, facebook style tooltips for jquery
|
||||
// version 1.0.0a
|
||||
// (c) 2008-2010 jason frame [jason@onehackoranother.com]
|
||||
// released under the MIT license
|
||||
|
||||
(function($) {
|
||||
|
||||
function maybeCall(thing, ctx) {
|
||||
return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
|
||||
}
|
||||
|
||||
function Tipsy(element, options) {
|
||||
this.$element = $(element);
|
||||
this.options = options;
|
||||
this.enabled = true;
|
||||
this.fixTitle();
|
||||
}
|
||||
|
||||
Tipsy.prototype = {
|
||||
show: function() {
|
||||
var title = this.getTitle();
|
||||
if (title && this.enabled) {
|
||||
var $tip = this.tip();
|
||||
|
||||
$tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
|
||||
$tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
|
||||
$tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).prependTo(document.body);
|
||||
|
||||
var pos = $.extend({}, this.$element.offset(), {
|
||||
width: this.$element[0].offsetWidth || 0,
|
||||
height: this.$element[0].offsetHeight || 0
|
||||
});
|
||||
|
||||
if (typeof this.$element[0].nearestViewportElement == 'object') {
|
||||
// SVG
|
||||
var el = this.$element[0];
|
||||
var rect = el.getBoundingClientRect();
|
||||
pos.width = rect.width;
|
||||
pos.height = rect.height;
|
||||
}
|
||||
|
||||
|
||||
var actualWidth = $tip[0].offsetWidth,
|
||||
actualHeight = $tip[0].offsetHeight,
|
||||
gravity = maybeCall(this.options.gravity, this.$element[0]);
|
||||
|
||||
var tp;
|
||||
switch (gravity.charAt(0)) {
|
||||
case 'n':
|
||||
tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
||||
break;
|
||||
case 's':
|
||||
tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
|
||||
break;
|
||||
case 'e':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
|
||||
break;
|
||||
case 'w':
|
||||
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
|
||||
break;
|
||||
}
|
||||
|
||||
if (gravity.length == 2) {
|
||||
if (gravity.charAt(1) == 'w') {
|
||||
tp.left = pos.left + pos.width / 2 - 15;
|
||||
} else {
|
||||
tp.left = pos.left + pos.width / 2 - actualWidth + 15;
|
||||
}
|
||||
}
|
||||
|
||||
$tip.css(tp).addClass('tipsy-' + gravity);
|
||||
$tip.find('.tipsy-arrow')[0].className = 'tipsy-arrow tipsy-arrow-' + gravity.charAt(0);
|
||||
if (this.options.className) {
|
||||
$tip.addClass(maybeCall(this.options.className, this.$element[0]));
|
||||
}
|
||||
|
||||
if (this.options.fade) {
|
||||
$tip.stop().css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: this.options.opacity});
|
||||
} else {
|
||||
$tip.css({visibility: 'visible', opacity: this.options.opacity});
|
||||
}
|
||||
|
||||
var t = this;
|
||||
var set_hovered = function(set_hover){
|
||||
return function(){
|
||||
t.$tip.stop();
|
||||
t.tipHovered = set_hover;
|
||||
if (!set_hover){
|
||||
if (t.options.delayOut === 0) {
|
||||
t.hide();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
if (t.hoverState == 'out') t.hide(); }, t.options.delayOut);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
$tip.hover(set_hovered(true), set_hovered(false));
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (this.options.fade) {
|
||||
this.tip().stop().fadeOut(function() { $(this).remove(); });
|
||||
} else {
|
||||
this.tip().remove();
|
||||
}
|
||||
},
|
||||
|
||||
fixTitle: function() {
|
||||
var $e = this.$element;
|
||||
|
||||
if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
|
||||
$e.attr('original-title', $e.attr('title') || '').removeAttr('title');
|
||||
}
|
||||
if (typeof $e.context.nearestViewportElement == 'object'){
|
||||
if ($e.children('title').length){
|
||||
$e.append('<original-title>' + ($e.children('title').text() || '') + '</original-title>')
|
||||
.children('title').remove();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getTitle: function() {
|
||||
|
||||
var title, $e = this.$element, o = this.options;
|
||||
this.fixTitle();
|
||||
|
||||
if (typeof o.title == 'string') {
|
||||
var title_name = o.title == 'title' ? 'original-title' : o.title;
|
||||
if ($e.children(title_name).length){
|
||||
title = $e.children(title_name).html();
|
||||
} else{
|
||||
title = $e.attr(title_name);
|
||||
}
|
||||
|
||||
} else if (typeof o.title == 'function') {
|
||||
title = o.title.call($e[0]);
|
||||
}
|
||||
title = ('' + title).replace(/(^\s*|\s*$)/, "");
|
||||
return title || o.fallback;
|
||||
},
|
||||
|
||||
tip: function() {
|
||||
if (!this.$tip) {
|
||||
this.$tip = $('<div class="tipsy"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
|
||||
}
|
||||
return this.$tip;
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
if (!this.$element[0].parentNode) {
|
||||
this.hide();
|
||||
this.$element = null;
|
||||
this.options = null;
|
||||
}
|
||||
},
|
||||
|
||||
enable: function() { this.enabled = true; },
|
||||
disable: function() { this.enabled = false; },
|
||||
toggleEnabled: function() { this.enabled = !this.enabled; }
|
||||
};
|
||||
|
||||
$.fn.tipsy = function(options) {
|
||||
|
||||
if (options === true) {
|
||||
return this.data('tipsy');
|
||||
} else if (typeof options == 'string') {
|
||||
var tipsy = this.data('tipsy');
|
||||
if (tipsy) tipsy[options]();
|
||||
return this;
|
||||
}
|
||||
|
||||
options = $.extend({}, $.fn.tipsy.defaults, options);
|
||||
|
||||
if (options.hoverlock && options.delayOut === 0) {
|
||||
options.delayOut = 100;
|
||||
}
|
||||
|
||||
function get(ele) {
|
||||
var tipsy = $.data(ele, 'tipsy');
|
||||
if (!tipsy) {
|
||||
tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
|
||||
$.data(ele, 'tipsy', tipsy);
|
||||
}
|
||||
return tipsy;
|
||||
}
|
||||
|
||||
function enter() {
|
||||
var tipsy = get(this);
|
||||
tipsy.hoverState = 'in';
|
||||
if (options.delayIn === 0) {
|
||||
tipsy.show();
|
||||
} else {
|
||||
tipsy.fixTitle();
|
||||
setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
|
||||
}
|
||||
}
|
||||
|
||||
function leave() {
|
||||
var tipsy = get(this);
|
||||
tipsy.hoverState = 'out';
|
||||
if (options.delayOut === 0) {
|
||||
tipsy.hide();
|
||||
} else {
|
||||
var to = function() {
|
||||
if (!tipsy.tipHovered || !options.hoverlock){
|
||||
if (tipsy.hoverState == 'out') tipsy.hide();
|
||||
}
|
||||
};
|
||||
setTimeout(to, options.delayOut);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.trigger != 'manual') {
|
||||
var binder = options.live ? 'live' : 'bind',
|
||||
eventIn = options.trigger == 'hover' ? 'mouseenter' : 'focus',
|
||||
eventOut = options.trigger == 'hover' ? 'mouseleave' : 'blur';
|
||||
this[binder](eventIn, enter)[binder](eventOut, leave);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
$.fn.tipsy.defaults = {
|
||||
className: null,
|
||||
delayIn: 0,
|
||||
delayOut: 0,
|
||||
fade: false,
|
||||
fallback: '',
|
||||
gravity: 'n',
|
||||
html: false,
|
||||
live: false,
|
||||
offset: 0,
|
||||
opacity: 0.8,
|
||||
title: 'title',
|
||||
trigger: 'hover',
|
||||
hoverlock: false
|
||||
};
|
||||
|
||||
// Overwrite this method to provide options on a per-element basis.
|
||||
// For example, you could store the gravity in a 'tipsy-gravity' attribute:
|
||||
// return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
|
||||
// (remember - do not modify 'options' in place!)
|
||||
$.fn.tipsy.elementOptions = function(ele, options) {
|
||||
return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
|
||||
};
|
||||
|
||||
$.fn.tipsy.autoNS = function() {
|
||||
return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
|
||||
};
|
||||
|
||||
$.fn.tipsy.autoWE = function() {
|
||||
return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
|
||||
};
|
||||
|
||||
/**
|
||||
* yields a closure of the supplied parameters, producing a function that takes
|
||||
* no arguments and is suitable for use as an autogravity function like so:
|
||||
*
|
||||
* @param margin (int) - distance from the viewable region edge that an
|
||||
* element should be before setting its tooltip's gravity to be away
|
||||
* from that edge.
|
||||
* @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
|
||||
* if there are no viewable region edges effecting the tooltip's
|
||||
* gravity. It will try to vary from this minimally, for example,
|
||||
* if 'sw' is preferred and an element is near the right viewable
|
||||
* region edge, but not the top edge, it will set the gravity for
|
||||
* that element's tooltip to be 'se', preserving the southern
|
||||
* component.
|
||||
*/
|
||||
$.fn.tipsy.autoBounds = function(margin, prefer) {
|
||||
return function() {
|
||||
var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
|
||||
boundTop = $(document).scrollTop() + margin,
|
||||
boundLeft = $(document).scrollLeft() + margin,
|
||||
$this = $(this);
|
||||
|
||||
if ($this.offset().top < boundTop) dir.ns = 'n';
|
||||
if ($this.offset().left < boundLeft) dir.ew = 'w';
|
||||
if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
|
||||
if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
|
||||
|
||||
return dir.ns + (dir.ew ? dir.ew : '');
|
||||
};
|
||||
};
|
||||
})(jQuery);
|
||||
Generated
Vendored
+112
@@ -0,0 +1,112 @@
|
||||
<!doctype html>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>Dagre D3 Demo: User-defined Shapes and Arrows</title>
|
||||
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>
|
||||
<script src="../dagre-d3.js"></script>
|
||||
|
||||
<style id="css">
|
||||
body {
|
||||
font: 300 14px 'Helvetica Neue', Helvetica;
|
||||
}
|
||||
|
||||
.node rect,
|
||||
.node circle,
|
||||
.node ellipse,
|
||||
.node polygon {
|
||||
stroke: #333;
|
||||
fill: #fff;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.edgePath path.path {
|
||||
stroke: #333;
|
||||
fill: none;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Dagre D3 Demo: User-defined Shapes and Arrows</h1>
|
||||
|
||||
<svg width=960 height=600><g/></svg>
|
||||
|
||||
<section>
|
||||
<p>An example that shows how to create and use user-defined shapes and arrows.
|
||||
</section>
|
||||
|
||||
<script id="js">
|
||||
// Create a new directed graph
|
||||
var g = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
g.setNode("house", { shape: "house", label: "house" });
|
||||
g.setNode("rect", { shape: "rect" });
|
||||
g.setEdge("house", "rect", { arrowhead: "hollowPoint" });
|
||||
|
||||
var svg = d3.select("svg"),
|
||||
inner = svg.select("g");
|
||||
|
||||
// Set up zoom support
|
||||
var zoom = d3.zoom().on("zoom", function() {
|
||||
inner.attr("transform", d3.event.transform);
|
||||
});
|
||||
svg.call(zoom);
|
||||
|
||||
// Create the renderer
|
||||
var render = new dagreD3.render();
|
||||
|
||||
// Add our custom shape (a house)
|
||||
render.shapes().house = function(parent, bbox, node) {
|
||||
var w = bbox.width,
|
||||
h = bbox.height,
|
||||
points = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: w, y: 0 },
|
||||
{ x: w, y: -h },
|
||||
{ x: w/2, y: -h * 3/2 },
|
||||
{ x: 0, y: -h }
|
||||
];
|
||||
shapeSvg = parent.insert("polygon", ":first-child")
|
||||
.attr("points", points.map(function(d) { return d.x + "," + d.y; }).join(" "))
|
||||
.attr("transform", "translate(" + (-w/2) + "," + (h * 3/4) + ")");
|
||||
|
||||
node.intersect = function(point) {
|
||||
return dagreD3.intersect.polygon(node, points, point);
|
||||
};
|
||||
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
// Add our custom arrow (a hollow-point)
|
||||
render.arrows().hollowPoint = function normal(parent, id, edge, type) {
|
||||
var marker = parent.append("marker")
|
||||
.attr("id", id)
|
||||
.attr("viewBox", "0 0 10 10")
|
||||
.attr("refX", 9)
|
||||
.attr("refY", 5)
|
||||
.attr("markerUnits", "strokeWidth")
|
||||
.attr("markerWidth", 8)
|
||||
.attr("markerHeight", 6)
|
||||
.attr("orient", "auto");
|
||||
|
||||
var path = marker.append("path")
|
||||
.attr("d", "M 0 0 L 10 5 L 0 10 z")
|
||||
.style("stroke-width", 1)
|
||||
.style("stroke-dasharray", "1,0")
|
||||
.style("fill", "#fff")
|
||||
.style("stroke", "#333");
|
||||
dagreD3.util.applyStyle(path, edge[type + "Style"]);
|
||||
};
|
||||
|
||||
// Run the renderer. This is what draws the final graph.
|
||||
render(inner, g);
|
||||
|
||||
// Center the graph
|
||||
var initialScale = 0.75;
|
||||
svg.call(zoom.transform, d3.zoomIdentity.translate((svg.attr("width") - g.graph().width * initialScale) / 2, 20).scale(initialScale));
|
||||
|
||||
svg.attr('height', g.graph().height * initialScale + 40);
|
||||
</script>
|
||||
|
||||
<script src="demo.js"></script>
|
||||
Reference in New Issue
Block a user