How to still drag/interact with nodes with an adornment appearing on hover?

Hi,

In the “Hover Buttons” GoJS sample (https://gojs.net/latest/samples/hoverButtons.html), it uses an adornment to display two buttons to the side of the node when the mouse is hovered over it. However, in this demo, it appears that you can’t drag the node after the adornment appears (because there’s a delay, you can drag it before the adornment appears, but not after).

In general, with this demo’s setup, it seems like mouse events on the main node are blocked by the transparent “go.Placeholder” object in the adornment. This also means that I was seemingly unable to click on any buttons, editable text, or any other interactable element on the node when the adornment is up.

I was wondering how/if can we use an adornment to have buttons appear on the side like in the demo, but still be able to drag the base node and interact with buttons/text on the base node while the adornment is up?

Would a custom selection adornment work for your needs? Buttons in a Circular Adornment

This would also be more effective to allow the adornment to show up when using touch.

Would we be able to display a custom selection adornment on mouse hover? Or is this only possible when you click on the node first?

Selection adornments are displayed when a node is selected. So you could set node.isSelected in a mouseHover function, although this would be somewhat odd behavior.

Does a hover adornment like this work as you want it to? The drawback of this approach is the hover buttons don’t disappear until the mouse leaves one of the buttons themselves.

      var nodeHoverAdornment =
        $(go.Adornment, "Spot",
          {
            // hide the Adornment when the mouse leaves it
            mouseLeave: (e, obj) => {
              var ad = obj.part;
              ad.adornedPart.removeAdornment("mouseHover");
            }
          },
          $(go.Placeholder),
          $("Button",
            { alignment: go.Spot.Left, alignmentFocus: go.Spot.Right },
            { click: (e, obj) => alert("Hi!") },
            $(go.TextBlock, "Hi!")),
          $("Button",
            { alignment: go.Spot.Right, alignmentFocus: go.Spot.Left },
            { click: (e, obj) => alert("Bye") },
            $(go.TextBlock, "Bye"))
        );

The core problem here is that the adornment is shown above the part itself and gets the mouse events. That’s what allows it to be hidden when the mouse moves off, but also what prevents text editing.

Hm, yeah, I don’t think we’d want either behavior. We wouldn’t want the nodes to be selected on hover and we wouldn’t want the adornment to remain on the screen if the user moves the mouse away from the node but doesn’t ever enter/exit the adornment.

We had other approaches that felt a bit like hacks, but they could work if there isn’t a better solution. One would be to have our buttons/editable text as part of the adornment itself so that they could receive mouse events. However, we’d want these specific elements to appear even with the user isn’t hovering over the node. We thought maybe we could attempt to display the elements as part of the main node only when the mouse is not hovering over it, and then hide them on mouse hover so that the adornment can display those same elements which can be interacted with now. The buttons were able to be pressed in the adornment this way, however, I was running into an issue where the text within the adornment was not able to be edited (it had the “editable” flag selected, etc.). There were also issues aligning the adornment elements and the main node elements so that they wouldn’t jump around on mouse hover.

Another approach we had was to not use an adornment at all and to use a custom solution. We don’t want the node readjusting its position after we hide/reveal elements outside of its boundaries (these outside elements include “add” buttons to the left and right and a horizontal menu above the node), so a solution would be to have a sort of “bounding box” as an invisible (alpha value of 0) graphobject rectangle that extends past the main node and contains space for all the additional elements we’d display. Then, when we hover over the node, we can set the additional elements to be visible without the node shifting around its position. A downside to this solution is we have to do some awkward offsets/positioning of the elements and we’d have to do some tinkering with the ports positions so that they would appear to connect to the left and right of the main node’s shape. The selection outline would also go around the invisible bounding box rectangle rather than being around the main node’s shape.

Do you have any thoughts on either of these approaches?

Hmm, we’ll have to think about this.

1 Like

Can you just modify the original sample in question? If you remove both:

background: "transparent",

in the adornment, you will be able to drag the node. Or do you need more functionality than that?