feat: 后端全量更新 - 含所有本次需求
- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
This commit is contained in:
Executable
+589
@@ -0,0 +1,589 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Simple Block Editor</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<meta name="description" content="A simple block diagram editor that includes context menus for changing shapes and colors." />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<script src="../release/go.js"></script>
|
||||
<script src="../extensions/Figures.js"></script>
|
||||
<script src="../extensions/DrawCommandHandler.js"></script>
|
||||
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
|
||||
<script id="code">
|
||||
function init() {
|
||||
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
|
||||
var $ = go.GraphObject.make;
|
||||
|
||||
myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{
|
||||
padding: 20, // extra space when scrolled all the way
|
||||
grid: $(go.Panel, "Grid", // a simple 10x10 grid
|
||||
$(go.Shape, "LineH", { stroke: "lightgray", strokeWidth: 0.5 }),
|
||||
$(go.Shape, "LineV", { stroke: "lightgray", strokeWidth: 0.5 })
|
||||
),
|
||||
"draggingTool.isGridSnapEnabled": true,
|
||||
handlesDragDropForTopLevelParts: true,
|
||||
mouseDrop: function(e) {
|
||||
// when the selection is dropped in the diagram's background,
|
||||
// make sure the selected Parts no longer belong to any Group
|
||||
var ok = e.diagram.commandHandler.addTopLevelParts(e.diagram.selection, true);
|
||||
if (!ok) e.diagram.currentTool.doCancel();
|
||||
},
|
||||
commandHandler: $(DrawCommandHandler), // support offset copy-and-paste
|
||||
"clickCreatingTool.archetypeNodeData": { text: "NEW NODE" }, // create a new node by double-clicking in background
|
||||
"PartCreated": function(e) {
|
||||
var node = e.subject; // the newly inserted Node -- now need to snap its location to the grid
|
||||
node.location = node.location.copy().snapToGridPoint(e.diagram.grid.gridOrigin, e.diagram.grid.gridCellSize);
|
||||
setTimeout(function() { // and have the user start editing its text
|
||||
e.diagram.commandHandler.editTextBlock();
|
||||
}, 20);
|
||||
},
|
||||
"commandHandler.archetypeGroupData": { isGroup: true, text: "NEW GROUP" },
|
||||
"SelectionGrouped": function(e) {
|
||||
var group = e.subject;
|
||||
setTimeout(function() { // and have the user start editing its text
|
||||
e.diagram.commandHandler.editTextBlock();
|
||||
})
|
||||
},
|
||||
"LinkRelinked": function(e) {
|
||||
// re-spread the connections of other links connected with both old and new nodes
|
||||
var oldnode = e.parameter.part;
|
||||
oldnode.invalidateConnectedLinks();
|
||||
var link = e.subject;
|
||||
if (e.diagram.toolManager.linkingTool.isForwards) {
|
||||
link.toNode.invalidateConnectedLinks();
|
||||
} else {
|
||||
link.fromNode.invalidateConnectedLinks();
|
||||
}
|
||||
},
|
||||
"undoManager.isEnabled": true
|
||||
});
|
||||
|
||||
|
||||
// Node template
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
{
|
||||
locationSpot: go.Spot.Center, locationObjectName: "SHAPE",
|
||||
desiredSize: new go.Size(120, 60), minSize: new go.Size(40, 40),
|
||||
resizable: true, resizeCellSize: new go.Size(20, 20)
|
||||
},
|
||||
// these Bindings are TwoWay because the DraggingTool and ResizingTool modify the target properties
|
||||
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
|
||||
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
|
||||
$(go.Shape,
|
||||
{ // the border
|
||||
name: "SHAPE", fill: "white",
|
||||
portId: "", cursor: "pointer",
|
||||
fromLinkable: true, toLinkable: true,
|
||||
fromLinkableDuplicates: true, toLinkableDuplicates: true,
|
||||
fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides
|
||||
},
|
||||
new go.Binding("figure"),
|
||||
new go.Binding("fill"),
|
||||
new go.Binding("stroke", "color"),
|
||||
new go.Binding("strokeWidth", "thickness"),
|
||||
new go.Binding("strokeDashArray", "dash")),
|
||||
// this Shape prevents mouse events from reaching the middle of the port
|
||||
$(go.Shape, { width: 100, height: 40, strokeWidth: 0, fill: "transparent" }),
|
||||
$(go.TextBlock,
|
||||
{ margin: 1, textAlign: "center", overflow: go.TextBlock.OverflowEllipsis, editable: true },
|
||||
// this Binding is TwoWay due to the user editing the text with the TextEditingTool
|
||||
new go.Binding("text").makeTwoWay(),
|
||||
new go.Binding("stroke", "color"))
|
||||
);
|
||||
|
||||
myDiagram.nodeTemplate.toolTip =
|
||||
$("ToolTip", // show some detailed information
|
||||
$(go.Panel, "Vertical",
|
||||
{ maxSize: new go.Size(200, NaN) }, // limit width but not height
|
||||
$(go.TextBlock,
|
||||
{ font: "bold 10pt sans-serif", textAlign: "center" },
|
||||
new go.Binding("text")),
|
||||
$(go.TextBlock,
|
||||
{ font: "10pt sans-serif", textAlign: "center" },
|
||||
new go.Binding("text", "details"))
|
||||
)
|
||||
);
|
||||
|
||||
// Node selection adornment
|
||||
// Include four large triangular buttons so that the user can easily make a copy
|
||||
// of the node, move it to be in that direction relative to the original node,
|
||||
// and add a link to the new node.
|
||||
|
||||
function makeArrowButton(spot, fig) {
|
||||
var maker = function(e, shape) {
|
||||
e.handled = true;
|
||||
e.diagram.model.commit(function(m) {
|
||||
var selnode = shape.part.adornedPart;
|
||||
// create a new node in the direction of the spot
|
||||
var p = new go.Point().setRectSpot(selnode.actualBounds, spot);
|
||||
p.subtract(selnode.location);
|
||||
p.scale(2, 2);
|
||||
p.x += Math.sign(p.x) * 60;
|
||||
p.y += Math.sign(p.y) * 60;
|
||||
p.add(selnode.location);
|
||||
p.snapToGridPoint(e.diagram.grid.gridOrigin, e.diagram.grid.gridCellSize);
|
||||
// make the new node a copy of the selected node
|
||||
var nodedata = m.copyNodeData(selnode.data);
|
||||
// add to same group as selected node
|
||||
m.setGroupKeyForNodeData(nodedata, m.getGroupKeyForNodeData(selnode.data));
|
||||
m.addNodeData(nodedata); // add to model
|
||||
// create a link from the selected node to the new node
|
||||
var linkdata = { from: selnode.key, to: m.getKeyForNodeData(nodedata) };
|
||||
m.addLinkData(linkdata); // add to model
|
||||
// move the new node to the computed location, select it, and start to edit it
|
||||
var newnode = e.diagram.findNodeForData(nodedata);
|
||||
newnode.location = p;
|
||||
e.diagram.select(newnode);
|
||||
setTimeout(function() {
|
||||
e.diagram.commandHandler.editTextBlock();
|
||||
}, 20);
|
||||
});
|
||||
};
|
||||
return $(go.Shape,
|
||||
{
|
||||
figure: fig,
|
||||
alignment: spot, alignmentFocus: spot.opposite(),
|
||||
width: (spot.equals(go.Spot.Top) || spot.equals(go.Spot.Bottom)) ? 36 : 18,
|
||||
height: (spot.equals(go.Spot.Top) || spot.equals(go.Spot.Bottom)) ? 18 : 36,
|
||||
fill: "orange", strokeWidth: 0,
|
||||
isActionable: true, // needed because it's in an Adornment
|
||||
click: maker, contextClick: maker
|
||||
});
|
||||
}
|
||||
|
||||
// create a button that brings up the context menu
|
||||
function CMButton(options) {
|
||||
return $(go.Shape,
|
||||
{
|
||||
fill: "orange", stroke: "gray", background: "transparent",
|
||||
geometryString: "F1 M0 0 M0 4h4v4h-4z M6 4h4v4h-4z M12 4h4v4h-4z M0 12",
|
||||
isActionable: true, cursor: "context-menu",
|
||||
click: function(e, shape) {
|
||||
e.diagram.commandHandler.showContextMenu(shape.part.adornedPart);
|
||||
}
|
||||
},
|
||||
options || {});
|
||||
}
|
||||
|
||||
myDiagram.nodeTemplate.selectionAdornmentTemplate =
|
||||
$(go.Adornment, "Spot",
|
||||
$(go.Placeholder, { padding: 10 }),
|
||||
makeArrowButton(go.Spot.Top, "TriangleUp"),
|
||||
makeArrowButton(go.Spot.Left, "TriangleLeft"),
|
||||
makeArrowButton(go.Spot.Right, "TriangleRight"),
|
||||
makeArrowButton(go.Spot.Bottom, "TriangleDown"),
|
||||
CMButton({ alignment: new go.Spot(0.75, 0) })
|
||||
);
|
||||
|
||||
// Common context menu button definitions
|
||||
|
||||
// All buttons in context menu work on both click and contextClick,
|
||||
// in case the user context-clicks on the button.
|
||||
// All buttons modify the node data, not the Node, so the Bindings need not be TwoWay.
|
||||
|
||||
// A button-defining helper function that returns a click event handler.
|
||||
// PROPNAME is the name of the data property that should be set to the given VALUE.
|
||||
function ClickFunction(propname, value) {
|
||||
return function(e, obj) {
|
||||
e.handled = true; // don't let the click bubble up
|
||||
e.diagram.model.commit(function(m) {
|
||||
m.set(obj.part.adornedPart.data, propname, value);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Create a context menu button for setting a data property with a color value.
|
||||
function ColorButton(color, propname) {
|
||||
if (!propname) propname = "color";
|
||||
return $(go.Shape,
|
||||
{
|
||||
width: 16, height: 16, stroke: "lightgray", fill: color,
|
||||
margin: 1, background: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.stroke = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.stroke = "lightgray"; },
|
||||
click: ClickFunction(propname, color), contextClick: ClickFunction(propname, color)
|
||||
});
|
||||
}
|
||||
|
||||
function LightFillButtons() { // used by multiple context menus
|
||||
return [
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
ColorButton("white", "fill"), ColorButton("beige", "fill"), ColorButton("aliceblue", "fill"), ColorButton("lightyellow", "fill")
|
||||
)
|
||||
),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
ColorButton("lightgray", "fill"), ColorButton("lightgreen", "fill"), ColorButton("lightblue", "fill"), ColorButton("pink", "fill")
|
||||
)
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
function DarkColorButtons() { // used by multiple context menus
|
||||
return [
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
ColorButton("black"), ColorButton("green"), ColorButton("blue"), ColorButton("red")
|
||||
)
|
||||
),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
ColorButton("brown"), ColorButton("magenta"), ColorButton("purple"), ColorButton("orange")
|
||||
)
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
// Create a context menu button for setting a data property with a stroke width value.
|
||||
function ThicknessButton(sw, propname) {
|
||||
if (!propname) propname = "thickness";
|
||||
return $(go.Shape, "LineH",
|
||||
{
|
||||
width: 16, height: 16, strokeWidth: sw,
|
||||
margin: 1, background: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.background = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.background = "transparent"; },
|
||||
click: ClickFunction(propname, sw), contextClick: ClickFunction(propname, sw)
|
||||
});
|
||||
}
|
||||
|
||||
// Create a context menu button for setting a data property with a stroke dash Array value.
|
||||
function DashButton(dash, propname) {
|
||||
if (!propname) propname = "dash";
|
||||
return $(go.Shape, "LineH",
|
||||
{
|
||||
width: 24, height: 16, strokeWidth: 2,
|
||||
strokeDashArray: dash,
|
||||
margin: 1, background: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.background = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.background = "transparent"; },
|
||||
click: ClickFunction(propname, dash), contextClick: ClickFunction(propname, dash)
|
||||
});
|
||||
}
|
||||
|
||||
function StrokeOptionsButtons() { // used by multiple context menus
|
||||
return [
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
ThicknessButton(1), ThicknessButton(2), ThicknessButton(3), ThicknessButton(4)
|
||||
)
|
||||
),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
DashButton(null), DashButton([2, 4]), DashButton([4, 4])
|
||||
)
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
// Node context menu
|
||||
|
||||
function FigureButton(fig, propname) {
|
||||
if (!propname) propname = "figure";
|
||||
return $(go.Shape,
|
||||
{
|
||||
width: 32, height: 32, scale: 0.5, fill: "lightgray", figure: fig,
|
||||
margin: 1, background: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.fill = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.fill = "lightgray"; },
|
||||
click: ClickFunction(propname, fig), contextClick: ClickFunction(propname, fig)
|
||||
});
|
||||
}
|
||||
|
||||
myDiagram.nodeTemplate.contextMenu =
|
||||
$("ContextMenu",
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
FigureButton("Rectangle"), FigureButton("RoundedRectangle"), FigureButton("Ellipse"), FigureButton("Diamond")
|
||||
)
|
||||
),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
FigureButton("Parallelogram2"), FigureButton("ManualOperation"), FigureButton("Procedure"), FigureButton("Cylinder1")
|
||||
)
|
||||
),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
FigureButton("Terminator"), FigureButton("CreateRequest"), FigureButton("Document"), FigureButton("TriangleDown")
|
||||
)
|
||||
),
|
||||
LightFillButtons(),
|
||||
DarkColorButtons(),
|
||||
StrokeOptionsButtons()
|
||||
);
|
||||
|
||||
|
||||
// Group template
|
||||
|
||||
myDiagram.groupTemplate =
|
||||
$(go.Group, "Spot",
|
||||
{
|
||||
layerName: "Background",
|
||||
ungroupable: true,
|
||||
locationSpot: go.Spot.Center,
|
||||
selectionObjectName: "BODY",
|
||||
computesBoundsAfterDrag: true, // allow dragging out of a Group that uses a Placeholder
|
||||
handlesDragDropForMembers: true, // don't need to define handlers on Nodes and Links
|
||||
mouseDrop: function(e, grp) { // add dropped nodes as members of the group
|
||||
var ok = grp.addMembers(grp.diagram.selection, true);
|
||||
if (!ok) grp.diagram.currentTool.doCancel();
|
||||
},
|
||||
avoidable: false
|
||||
},
|
||||
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
|
||||
$(go.Panel, "Auto",
|
||||
{ name: "BODY" },
|
||||
$(go.Shape,
|
||||
{
|
||||
parameter1: 10,
|
||||
fill: "white", strokeWidth: 2,
|
||||
portId: "", cursor: "pointer",
|
||||
fromLinkable: true, toLinkable: true,
|
||||
fromLinkableDuplicates: true, toLinkableDuplicates: true,
|
||||
fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides
|
||||
},
|
||||
new go.Binding("fill"),
|
||||
new go.Binding("stroke", "color"),
|
||||
new go.Binding("strokeWidth", "thickness"),
|
||||
new go.Binding("strokeDashArray", "dash")),
|
||||
$(go.Placeholder,
|
||||
{ background: "transparent", margin: 10 })
|
||||
),
|
||||
$(go.TextBlock,
|
||||
{
|
||||
alignment: go.Spot.Top, alignmentFocus: go.Spot.Bottom,
|
||||
font: "bold 12pt sans-serif", editable: true
|
||||
},
|
||||
new go.Binding("text"),
|
||||
new go.Binding("stroke", "color"))
|
||||
);
|
||||
|
||||
myDiagram.groupTemplate.selectionAdornmentTemplate =
|
||||
$(go.Adornment, "Spot",
|
||||
$(go.Panel, "Auto",
|
||||
$(go.Shape, { fill: null, stroke: "dodgerblue", strokeWidth: 3 }),
|
||||
$(go.Placeholder, { margin: 1.5 })
|
||||
),
|
||||
CMButton({ alignment: go.Spot.TopRight, alignmentFocus: go.Spot.BottomRight })
|
||||
);
|
||||
|
||||
myDiagram.groupTemplate.contextMenu =
|
||||
$("ContextMenu",
|
||||
LightFillButtons(),
|
||||
DarkColorButtons(),
|
||||
StrokeOptionsButtons()
|
||||
);
|
||||
|
||||
|
||||
// Link template
|
||||
|
||||
myDiagram.linkTemplate =
|
||||
$(go.Link,
|
||||
{
|
||||
layerName: "Foreground",
|
||||
routing: go.Link.AvoidsNodes, corner: 10,
|
||||
toShortLength: 4, // assume arrowhead at "to" end, need to avoid bad appearance when path is thick
|
||||
relinkableFrom: true, relinkableTo: true,
|
||||
reshapable: true, resegmentable: true
|
||||
},
|
||||
new go.Binding("fromSpot", "fromSpot", go.Spot.parse),
|
||||
new go.Binding("toSpot", "toSpot", go.Spot.parse),
|
||||
new go.Binding("fromShortLength", "dir", function(dir) { return dir === 2 ? 4 : 0; }),
|
||||
new go.Binding("toShortLength", "dir", function(dir) { return dir >= 1 ? 4 : 0; }),
|
||||
new go.Binding("points").makeTwoWay(), // TwoWay due to user reshaping with LinkReshapingTool
|
||||
$(go.Shape, { strokeWidth: 2 },
|
||||
new go.Binding("stroke", "color"),
|
||||
new go.Binding("strokeWidth", "thickness"),
|
||||
new go.Binding("strokeDashArray", "dash")),
|
||||
$(go.Shape, { fromArrow: "Backward", strokeWidth: 0, scale: 4/3, visible: false },
|
||||
new go.Binding("visible", "dir", function(dir) { return dir === 2; }),
|
||||
new go.Binding("fill", "color"),
|
||||
new go.Binding("scale", "thickness", function(t) { return (2+t)/3; })),
|
||||
$(go.Shape, { toArrow: "Standard", strokeWidth: 0, scale: 4/3 },
|
||||
new go.Binding("visible", "dir", function(dir) { return dir >= 1; }),
|
||||
new go.Binding("fill", "color"),
|
||||
new go.Binding("scale", "thickness", function(t) { return (2+t)/3; })),
|
||||
$(go.TextBlock,
|
||||
{ alignmentFocus: new go.Spot(0, 1, -4, 0), editable: true },
|
||||
new go.Binding("text").makeTwoWay(), // TwoWay due to user editing with TextEditingTool
|
||||
new go.Binding("stroke", "color"))
|
||||
);
|
||||
|
||||
myDiagram.linkTemplate.selectionAdornmentTemplate =
|
||||
$(go.Adornment, // use a special selection Adornment that does not obscure the link path itself
|
||||
$(go.Shape,
|
||||
{ // this uses a pathPattern with a gap in it, in order to avoid drawing on top of the link path Shape
|
||||
isPanelMain: true,
|
||||
stroke: "transparent", strokeWidth: 6,
|
||||
pathPattern: makeAdornmentPathPattern(2) // == thickness or strokeWidth
|
||||
},
|
||||
new go.Binding("pathPattern", "thickness", makeAdornmentPathPattern)),
|
||||
CMButton({ alignmentFocus: new go.Spot(0, 0, -6, -4) })
|
||||
);
|
||||
|
||||
function makeAdornmentPathPattern(w) {
|
||||
return $(go.Shape,
|
||||
{
|
||||
stroke: "dodgerblue", strokeWidth: 2, strokeCap: "square",
|
||||
geometryString: "M0 0 M4 2 H3 M4 " + (w+4).toString() + " H3"
|
||||
});
|
||||
}
|
||||
|
||||
// Link context menu
|
||||
// All buttons in context menu work on both click and contextClick,
|
||||
// in case the user context-clicks on the button.
|
||||
// All buttons modify the link data, not the Link, so the Bindings need not be TwoWay.
|
||||
|
||||
function ArrowButton(num) {
|
||||
var geo = "M0 0 M16 16 M0 8 L16 8 M12 11 L16 8 L12 5";
|
||||
if (num === 0) {
|
||||
geo = "M0 0 M16 16 M0 8 L16 8";
|
||||
} else if (num === 2) {
|
||||
geo = "M0 0 M16 16 M0 8 L16 8 M12 11 L16 8 L12 5 M4 11 L0 8 L4 5";
|
||||
}
|
||||
return $(go.Shape,
|
||||
{
|
||||
geometryString: geo,
|
||||
margin: 2, background: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.background = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.background = "transparent"; },
|
||||
click: ClickFunction("dir", num), contextClick: ClickFunction("dir", num)
|
||||
});
|
||||
}
|
||||
|
||||
function AllSidesButton(to) {
|
||||
var setter = function(e, shape) {
|
||||
e.handled = true;
|
||||
e.diagram.model.commit(function(m) {
|
||||
var link = shape.part.adornedPart;
|
||||
m.set(link.data, (to ? "toSpot" : "fromSpot"), go.Spot.stringify(go.Spot.AllSides));
|
||||
// re-spread the connections of other links connected with the node
|
||||
(to ? link.toNode : link.fromNode).invalidateConnectedLinks();
|
||||
});
|
||||
};
|
||||
return $(go.Shape,
|
||||
{
|
||||
width: 12, height: 12, fill: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.background = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.background = "transparent"; },
|
||||
click: setter, contextClick: setter
|
||||
});
|
||||
}
|
||||
|
||||
function SpotButton(spot, to) {
|
||||
var ang = 0;
|
||||
var side = go.Spot.RightSide;
|
||||
if (spot.equals(go.Spot.Top)) { ang = 270; side = go.Spot.TopSide; }
|
||||
else if (spot.equals(go.Spot.Left)) { ang = 180; side = go.Spot.LeftSide; }
|
||||
else if (spot.equals(go.Spot.Bottom)) { ang = 90; side = go.Spot.BottomSide; }
|
||||
if (!to) ang -= 180;
|
||||
var setter = function(e, shape) {
|
||||
e.handled = true;
|
||||
e.diagram.model.commit(function(m) {
|
||||
var link = shape.part.adornedPart;
|
||||
m.set(link.data, (to ? "toSpot" : "fromSpot"), go.Spot.stringify(side));
|
||||
// re-spread the connections of other links connected with the node
|
||||
(to ? link.toNode : link.fromNode).invalidateConnectedLinks();
|
||||
});
|
||||
};
|
||||
return $(go.Shape,
|
||||
{
|
||||
alignment: spot, alignmentFocus: spot.opposite(),
|
||||
geometryString: "M0 0 M12 12 M12 6 L1 6 L4 4 M1 6 L4 8",
|
||||
angle: ang,
|
||||
background: "transparent",
|
||||
mouseEnter: function(e, shape) { shape.background = "dodgerblue"; },
|
||||
mouseLeave: function(e, shape) { shape.background = "transparent"; },
|
||||
click: setter, contextClick: setter
|
||||
});
|
||||
}
|
||||
|
||||
myDiagram.linkTemplate.contextMenu =
|
||||
$("ContextMenu",
|
||||
DarkColorButtons(),
|
||||
StrokeOptionsButtons(),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
ArrowButton(0), ArrowButton(1), ArrowButton(2)
|
||||
)
|
||||
),
|
||||
$("ContextMenuButton",
|
||||
$(go.Panel, "Horizontal",
|
||||
$(go.Panel, "Spot",
|
||||
AllSidesButton(false),
|
||||
SpotButton(go.Spot.Top, false), SpotButton(go.Spot.Left, false), SpotButton(go.Spot.Right, false), SpotButton(go.Spot.Bottom, false)
|
||||
),
|
||||
$(go.Panel, "Spot",
|
||||
{ margin: new go.Margin(0, 0, 0, 2) },
|
||||
AllSidesButton(true),
|
||||
SpotButton(go.Spot.Top, true), SpotButton(go.Spot.Left, true), SpotButton(go.Spot.Right, true), SpotButton(go.Spot.Bottom, true)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
// save a model to and load a model from JSON-formatted text, displayed below the Diagram
|
||||
function save() {
|
||||
var str = myDiagram.model.toJson();
|
||||
document.getElementById("mySavedModel").value = str;
|
||||
}
|
||||
function load() {
|
||||
var str = document.getElementById("mySavedModel").value;
|
||||
myDiagram.model = go.Model.fromJson(str);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<div id="sample">
|
||||
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
|
||||
<p>
|
||||
Double-click in the background to create a new node.
|
||||
Create groups by selecting nodes and invoking Ctrl-G; Ctrl-Shift-G to ungroup a selected group.
|
||||
A selected node will have four orange triangles that when clicked will automatically copy the node and link to it.
|
||||
Use the context menu to change the shape, color, thickness, and dashed-ness.
|
||||
</p>
|
||||
<p>
|
||||
Links can be drawn by dragging from the side of each node.
|
||||
A selected link can be reconnected by dragging an end handle.
|
||||
Use the context menu to change the color, thickness, dashed-ness, and which side the link should connect with.
|
||||
</p>
|
||||
<div id="buttons">
|
||||
<button id="loadModel" onclick="load()">Load</button>
|
||||
<button id="saveModel" onclick="save()">Save</button>
|
||||
</div>
|
||||
<textarea id="mySavedModel" style="width:100%;height:300px">
|
||||
{ "class": "GraphLinksModel",
|
||||
"nodeDataArray": [
|
||||
{"key":1, "loc":"0 0", "text":"Alpha", "details":"some information about Alpha and its importance"},
|
||||
{"key":2, "loc":"170 0", "text":"Beta", "color":"blue", "thickness":2, "figure":"Procedure"},
|
||||
{"key":3, "loc":"0 100", "text":"Gamma", "color":"green", "figure":"Cylinder1"},
|
||||
{"key":4, "loc":"80 180", "text":"Delta", "color":"red", "figure":"Terminator", "size":"80 40"},
|
||||
{"key":5, "loc":"350 -50", "text":"Zeta", "group":7, "color":"blue", "figure":"CreateRequest"},
|
||||
{"key":6, "loc":"350 50", "text":"Eta", "group":7, "figure":"Document", "fill":"lightyellow"},
|
||||
{"key":7, "isGroup":true, "text":"Theta", "color":"green", "fill":"lightgreen"},
|
||||
{"key":8, "loc":"520 50", "text":"Iota", "fill":"pink"}
|
||||
],
|
||||
"linkDataArray": [
|
||||
{"from":1, "to":2, "dash":[ 6,3 ], "thickness":4},
|
||||
{"from":1, "to":3, "dash":[ 2,4 ], "color":"green", "text":"label"},
|
||||
{"from":3, "to":4, "color":"red", "text":"a red label", "fromSpot":"RightSide"},
|
||||
{"from":2, "to":1},
|
||||
{"from":5, "to":6, "text":"in a group"},
|
||||
{"from":2, "to":7},
|
||||
{"from":6, "to":8, "dir":0},
|
||||
{"from":6, "to":8, "dir":1},
|
||||
{"from":6, "to":8, "dir":2}
|
||||
]}
|
||||
</textarea>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user