GoJS tooltip questions

I am currently using toolManager.linkingTool.linkValidation to fire a tool tip on the diagram if the connection is invalid. However, putting

const tt = ( 'ToolTip', { 'Border.stroke': 'red' }, (
go.TextBlock,
{ margin: 4 },
message here
)
)
myDiagram.toolManager.showToolTip(tt, toport)

only allows the tool tip to fire once (the first time a connection between two ports has been made). The user will have to stop the link and re-attempt the link to see the error again. Is it possible to make it fire every time a link to a port has been made?

Additionally, the tooltip auto hides after roughly 10 seconds. Is it possible to make it so that it hides only when the mouse has been moved?

similar to: Increase Tooltip delay
but for gojs?

Does this help? https://gojs.net/extras/linkValidationToolTip.html

And maybe this: https://gojs.net/latest/api/symbols/ToolManager.html#toolTipDuration

Hi Walter,

This is really close to what I wish to achieve. If I would like to select the last port selected instead of node, how would I do so? I was unsure what to change for the parameters of findPartAt.

Would I also be changing it from if(node instanceof go.Node) to if(port instanceof go.Spot) ?

All ports are GraphObjects, so none will be instanceof go.Spot.

Diagram.findPartAt naturally only finds Parts: Nodes or Links. If you have separate ports on your nodes, you’ll want to call Diagram.findObjectAt. But if your ports are small, maybe you really want to call Diagram.findObjectsNear, so that the user doesn’t have to be so precise.

this.diagram.findObjectsNear(p, 30, getPort, null, true)

I haven’t tested this at all:

function getPort(x) {
  if (!x) return null;
  if (x.portId !== null) return x;
  if (x.panel) return getPort(x.panel);
  if (x instanceof go.Node) return x.port;
  return null;
}

I am testing with the code you provided.

If I console.log

const port = this.diagram.findObjectsNear(
          this.diagram.lastInput.documentPoint,
          30,
          getPort,
          null,
          true
        )

When I hover my cursor over a port, it returns and object with an object named Eb. There are 3 more nested objects with keys. The second one seems to be the node and the 3rd one seems to be the port.

If I try

const port = this.diagram.findObjectAt(
          this.diagram.lastInput.documentPoint,
          function(x) {
            return x.part
          },
          // Because of the navigation function, x will always be a Part.
          function(x) {
            return x.canSelect()
          }
        )

It kind of works but the tooltip is firing where ever the cursor is with the statement: if (port instanceof go.GraphObject)

Reading what GraphObject is, it makes sense. Is there a a typing specifically for ports?

Diagram.findObjectsNear returns a collection of GraphObjects, not a single GraphObject.

No, that’s why I gave you the getPort function. Which I hope works, but I have not tried it.

I was not able to get it to work with the code provided but I altered it a bit to get the specific port it is hovered with using getObjectsAt.

const port = this.diagram.findObjectsAt(
          this.diagram.lastInput.documentPoint,
          getPort
        )
        function getPort(x) {
          if (!x) return null
          if (x.panel) {
            console.log('there is an id', x.panel.portId)
            if (x.panel.portId) return x
          }
          return null
        }
        console.log('what is port?', port)
        if (port instanceof go.GraphObject) {
          console.log('detected') //this is never triggered

          if (this.diagram.toolManager.currentToolTip === null) {
            const tt = $(
              'ToolTip',
              { 'Border.stroke': 'red' },
              $(
                go.TextBlock,
                { margin: 4 },
                `Unable to link nodes due to output mismatch. \n
                          Ports have either different dimensions or typings.`
              )
            )
            this.diagram.toolManager.showToolTip(tt, port)
          }
        } else {
          this.diagram.toolManager.hideToolTip()
        }

I was able to get the return value of getObjectsAt to return specifically the port. I can not use objectNear because some of my nodes have multiple ports.

However, I do not understand how to manipulate what is returned. The API documentation says it returns a collection of GraphObjects. How do I access the GraphObject within the collection? If I print port, it returns an object with multiple double letter objects nested. The object ‘Eb’ contains the single object with the port with the key of ‘52161’. The count/size of the object returned by getObjectsAt is also 1 to confirm that there is only 1 object.

Well, if you only want the first item in a collection, call first() on it.

More generally, read about collections at https://gojs.net/latest/intro/collections.html. Set and Map were designed and implemented before the ES6 Set and Map were proposed, but we’ve made ours compatible except for iteration.

I was able to get it to work with .first and read up on collections. Thank you for that.

Is it possible to access to/from node/port information within setNoTargetPortProperties? Or is there a way to run the function passed through linkValidation for toolManager more than once?

Yes, that is the whole purpose of copyPortProperties and setNoTargetPortProperties.

The linking tools are optimized to cache the results of calling the validation predicates.