Here’s a complete stand-alone sample that shows nested Groups. Both Nodes and Groups have mouseEnter and mouseLeave event handlers that change the Shape.fill of one of their Shapes.
There is an unmodeled Part in the “Tool” Layer that acts as a visual indicator of where the virtual pointer is. The Robot instance is called to pretend to move the mouse along a path that goes downwards and leftwards, crossing over various Nodes and Groups. You can move that virtual pointer by clicking the only HTML button on the page.
I find that scrolling or zooming the diagram between button clicks does not break the behavior of the next call to move()
.
<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2024 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>
<button id="myTestButton">Shift virtual pointer left & down</button>
<script src="https://cdn.jsdelivr.net/npm/gojs/release/go.js"></script>
<script src="https://cdn.jsdelivr.net/npm/create-gojs-kit/dist/extensions/Robot.js"></script>
<script id="code">
const myDiagram =
new go.Diagram("myDiagramDiv");
myDiagram.nodeTemplate =
new go.Node("Auto", {
mouseEnter: (e, node) => node.findObject("SHP").fill = "yellow",
mouseLeave: (e, node) => node.findObject("SHP").fill = "lightgreen",
})
.add(
new go.Shape({ name: "SHP", fill: "lightgreen", stroke: "green" }),
new go.TextBlock({ margin: 8 })
.bind("text")
);
myDiagram.groupTemplate =
new go.Group("Vertical", {
mouseEnter: (e, node) => node.findObject("SHP").fill = "cyan",
mouseLeave: (e, node) => node.findObject("SHP").fill = "#CCCCCC08",
})
.add(
new go.TextBlock({ font: "bold 12pt sans-serif" })
.bind("text"),
new go.Panel("Auto")
.add(
new go.Shape({ name: "SHP", fill: "#CCCCCC08", strokeWidth: 2 }),
new go.Placeholder({ padding: 10 })
)
);
var myPointerX = 350
var myPointerY = -10;
const Pointer =
new go.Part({
layerName: "Tool",
locationSpot: go.Spot.Center,
location: new go.Point(myPointerX, myPointerY)
})
.add(
new go.Shape("PlusLine", { width: 30, height: 30, stroke: "magenta" })
);
myDiagram.add(Pointer);
const myRobot = new Robot(myDiagram);
var myRobotTime = 0;
function move() {
myPointerX -= 10; myPointerY += 8;
myRobot.mouseMove(myPointerX, myPointerY, myRobotTime);
Pointer.location = new go.Point(myPointerX, myPointerY);
myRobotTime += 100;
}
document.getElementById("myTestButton").addEventListener("click", e => move());
myDiagram.model = new go.GraphLinksModel([
{ key: 1, isGroup: true, text: "One" },
{ key: 2, isGroup: true, text: "Two" },
{ key: 11, isGroup: true, group: 1, text: "One one" },
{ key: 12, isGroup: true, group: 1, text: "One two" },
{ key: 13, group: 1, text: "One three" },
{ key: 121, group: 12, text: "One two one" },
{ key: 122, group: 12, text: "One two two" },
{ key: 123, group: 12, text: "One two three" },
{ key: 21, group: 2, text: "Two one" },
],
[
{ from: 1, to: 2 },
{ from: 11, to: 12 },
{ from: 12, to: 13 },
{ from: 121, to: 122 },
{ from: 122, to: 123 },
]);
</script>
</body>
</html>