TextBlock only truncating when half of the word is cut off

I have a left aligned TextBlock in a vertical Panel that’s in side a Rectangle. On mouseEnter of the Rectangle, I’m shrinking the TextBlock based on the width of the Rectangle like so:

    var textBlock = node.findObject(TEXTBLOCK_NAME);
    var rectangle = node.findObject(RECTANGLE_NAME);
    if (textBlock && rectangle && rectangle.measuredBounds) {
        textBlock.width = rectangle.measuredBounds.width - BUFFER_SIZE;
    }

where BUFFER_SIZE is some constant width.

My expected behavior is that the TextBlock would shrink and text like “Application Rejected” would become “Application Reje…”, but what I’m seeing is that the text only gets truncated when the word “Rejected” is cut off by half, i.e. I can only ever get “Application…” or “Application Rejected” even if there shouldn’t be room for the word “Rejected.” What am I missing here?

My TextBlock looks like this:

    $(go.TextBlock,
        new go.Binding("text", "label"),
         {
            name: TEXTBLOCK_NAME,
            margin: new go.Margin(4, 12, 0, 12),
            alignment: go.Spot.Left,
            overflow: go.TextBlock.OverflowEllipsis,
            maxLines: 1
        }
    ),

We are on version 2.1.56.

First I should say that:

will always be a reference to a Rect, so it can never be falsy.

When I try your code, it seems to show the ellipsis just fine. I took the liberty of adding a mouseLeave event handler that resets the TextBlock.width to NaN so that it can get its natural size back.

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2022 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      "undoManager.isEnabled": true
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    {
      mouseEnter: (e, node) => {
        const textBlock = node.findObject("TB");
        const rectangle = node;
        if (textBlock && rectangle) {
          textBlock.width = rectangle.measuredBounds.width - 30;
        }
      },
      mouseLeave: (e, node) => {
        const textBlock = node.findObject("TB");
        if (textBlock) {
          textBlock.width = NaN;
        }
      }
    },
    $(go.Shape,
      { fill: "white" },
      new go.Binding("fill", "color")),
    $(go.TextBlock,
      {
        name: "TB", margin: new go.Margin(4, 12, 0, 12),
        alignment: go.Spot.Left, overflow: go.TextBlock.OverflowEllipsis, maxLines: 1
      },
      new go.Binding("text"))
  );

myDiagram.model = new go.GraphLinksModel(
[
  { key: 1, text: "Alpha", color: "lightblue" },
  { key: 2, text: "Beta", color: "orange" },
  { key: 3, text: "Gamma", color: "lightgreen" },
  { key: 4, text: "Delta", color: "pink" }
],
[
  { from: 1, to: 2 },
  { from: 1, to: 3 },
  { from: 2, to: 2 },
  { from: 3, to: 4 },
  { from: 4, to: 1 }
]);
  </script>
</body>
</html>

I appreciate the other information!

However, I was able to recreate the issue in that example.
I added a set width to the shapes and on mouseEnter, I am now subtracting a bigger number.
Try hovering over the “Application Rejected” rectangle when subtracting 82 and notice that the text is not truncated. Then try changing it to 83 and notice that it truncates the whole word.

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2022 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      "undoManager.isEnabled": true
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    {
      mouseEnter: (e, node) => {
        const textBlock = node.findObject("TB");
        const rectangle = node;
        if (textBlock && rectangle) {
          textBlock.width = rectangle.measuredBounds.width - 82;
        }
      },
      mouseLeave: (e, node) => {
        const textBlock = node.findObject("TB");
        if (textBlock) {
          textBlock.width = NaN;
        }
      }
    },
    $(go.Shape,
      { fill: "white", width: 200 },
      new go.Binding("fill", "color")),
    $(go.TextBlock,
      {
        name: "TB", margin: new go.Margin(4, 12, 0, 12),
        alignment: go.Spot.Left, overflow: go.TextBlock.OverflowEllipsis, maxLines: 1
      },
      new go.Binding("text"))
  );

myDiagram.model = new go.GraphLinksModel(
[
  { key: 1, text: "Application Rejected", color: "lightblue" },
  { key: 2, text: "Beta", color: "orange" },
  { key: 3, text: "Gamma", color: "lightgreen" },
  { key: 4, text: "Delta", color: "pink" }
],
[
  { from: 1, to: 2 },
  { from: 1, to: 3 },
  { from: 2, to: 2 },
  { from: 3, to: 4 },
  { from: 4, to: 1 }
]);
  </script>
</body>
</html>

My guess is that as you make it narrower, eventually the computed width is negative, and in GoJS and in the real world you cannot have objects with negative width. That’s why nothing happens.

In this case, it’s not negative. We have 200 - 82 = 118 vs 200 - 83 = 117. In both cases, the word “Rejection” should have already been truncated, but it’s only when it’s over halfway cut off (when we subtract 83) that it truncates the entire word and instead shows “Application…” I would expect to see the in-between states of “Rejecte…”, “Reject…”, “Rejec…”, etc., but instead we get all or nothing, even if showing all would actually exceed the expected width.

I think the difference is that there is a space between the words, and the ellipsis algorithm has a preference for removing whole words first, and only then breaking off a piece of a word in order to fit into the given space.

In your example, if you change the text to be “ApplicationRejected” and try it with various values for the resulting width, you’ll see how it does elide in manners such as:
image
That was when subtracting 93 from the measured width of the node.

For example, after removing the maxLines setting, when still subtracting 93, with a space:
image
and without a space:
image

BTW, this is in Firefox; the behavior in Chrome may be different.

Is there a way to truncate parts of the final word in strings of text that contain spaces?

My initial claim that it has to be “over half way cut off” was wrong, as illustrated in the edited code below. I added a rectangle that visualizes how big the “buffer” is. With or without a space, we can see that the TextBlock takes up more area than you would expect its width to allow. Is there any workaround for this other than overcompensating with a bigger buffer?

This screenshot is with a buffer of 100 while hovering over the orange node.
image

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2022 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:400px"></div>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;
const buffer = 83;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      "undoManager.isEnabled": true
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    {
      mouseEnter: (e, node) => {
        const textBlock = node.findObject("TB");
        const rectangle = node;
        if (textBlock && rectangle) {
          textBlock.width = rectangle.measuredBounds.width - buffer;
        }
      },
      mouseLeave: (e, node) => {
        const textBlock = node.findObject("TB");
        if (textBlock) {
          textBlock.width = NaN;
        }
      }
    },
    $(go.Panel, "Spot",
        $(go.Shape,
             { fill: "white", width: 200 },
            new go.Binding("fill", "color")
        ),
        $(go.Shape, { fill: "red", width: buffer, height: 18, alignment: go.Spot.Right, alignmentFocus: go.Spot.Right})
        ),
    $(go.TextBlock,
      {
        name: "TB", margin: new go.Margin(4, 12, 0, 12),
        alignment: go.Spot.Left, overflow: go.TextBlock.OverflowEllipsis, maxLines: 1,

      },
      new go.Binding("text")),
  );

myDiagram.model = new go.GraphLinksModel(
[
  { key: 1, text: "Application Rejected", color: "lightblue" },
  { key: 2, text: "ApplicationRejected", color: "orange" },
  { key: 3, text: "Gamma", color: "lightgreen" },
  { key: 4, text: "Delta", color: "pink" }
],
[
  { from: 1, to: 2 },
  { from: 1, to: 3 },
  { from: 2, to: 2 },
  { from: 3, to: 4 },
  { from: 4, to: 1 }
]);
  </script>
</body>
</html>

If I understand you correctly, I think all you need to do is set

wrap: go.TextBlock.WrapBreakAll

in your TextBlock.

Note that your margins make the ends of the TextBlock cutoff look funny.

That’s it, thank you!