mouseLeave event triggered when moving into group node

In our code we have a group template:

$(go.Group,
      'Auto',
      {
        layout: $(go.GridLayout, {
          wrappingColumn: 6,
          alignment: go.GridLayout.Position,
          cellSize: new go.Size(1, 1),
          spacing: new go.Size(3, 3),
        }),
        selectable: false,
        movable: false,
        mouseEnter(e, obj, prev) {
          // do something
        },
        mouseLeave(e, obj, next) {
          // do the opposite
        },
      },
      $(go.Shape, {
        fill: 'rgba(99,99,99,0)',
        strokeWidth: 0,
        name: 'SHAPE',
      }),
      $(go.Placeholder, {
        padding: 5,
      }),
)

The mouseEnter seems to work, but as soon as you move onto a node inside of the group the mouseLeave event is triggered.

There are no mouseEnter events subscribed on the nodes.

How do I keep the mouseLeave event from triggering if I am still “inside” the group?

That is right – you could implement mouseEnter and mouseLeave event handlers on your Nodes and Links. Look at Part.containingGroup to see if the node or link is a member of a group.

By the way, although you are not asking about the case where the user is dragging Parts with the DraggingTool, if you were asking about that you could just set the Group | GoJS API property. But that property doesn’t help for the case that you are describing now.

EDIT: you can also get the effect by only defining the event handlers on the Group:

      $(go.Group, "Vertical",
        {
          mouseEnter: function(e, grp, prev) {
            if (prev instanceof go.Adornment) prev = prev.adornedPart;
            if (prev && prev.part.isMemberOf(grp)) {
              console.log("staying in Group " + grp.key + " out of " + prev.part.key);
            } else {
              console.log("Entering Group " + grp.key);
            }
          },
          mouseLeave: function(e, grp, next) {
            if (next instanceof go.Adornment) next = next.adornedPart;
            if (next && next.part.isMemberOf(grp)) {
              console.log("staying in Group " + grp.key + " into " + next.part.key);
            } else {
              console.log("Leaving Group " + grp.key);
            }
          }
        },
        . . .

Thanks for the example :-)
The code you provided for the mouseEnter in the group is working but it’s slightly buggy. Sometimes when moving to another group it does not pick up the mouseLeave event.

Let me clarify my use case:
I am trying to highlight the group with a stroke when the users mouse enters the group and then remove the highlight when the user leaves the group.

Of course, this is an oversimplification because I need to do more things but thats the gist of it.

In javascript I would just wrap my divs in another div and add an event listener on the wrapping div.
Is there no equivalent in gojs?

It occurs to me now that the code was not handling nested groups. I have modified that code, above, but I have not tested it.

You are being very vague what the problem was, so it’s hard for me to guess.

By the way, my code is assuming that “within” a group is defined by being “at” (Diagram.findObjectAt) an object that is in the visual tree of that group or of a part that is a member of that group, perhaps indirectly (nested groups) with the change to using Part.isMemberOf rather than just checking the immediate Part.containingGroup.

That means that if the mouse passes over a part that does not belong to the group, it leaves the group. That could happen, for example, when passing over a node that does not belong to the group but happens to be overlapping the group. Or more frequently when passing over a link whose both connected nodes are not in the group.

It also means that if the group has a hole in, geometrically speaking, and the mouse is in that hole, it is not in that group. That is not the case with your group template, but is a possibility in general.

If that does not match your expectations for “the mouse being inside a group”, then you will need to change the code accordingly.